mac_shortcuts 0.1
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 +7 -0
- data/bin/mac_shortcuts +9 -0
- data/lib/mac_shortcuts.rb +10 -0
- data/lib/mac_shortcuts/application_preferences_finder.rb +76 -0
- data/lib/mac_shortcuts/command.rb +23 -0
- data/lib/mac_shortcuts/command/set.rb +56 -0
- data/lib/mac_shortcuts/shortcut.rb +118 -0
- data/lib/mac_shortcuts/version.rb +4 -0
- data/mac_shortcuts.gemspec +30 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d91535e242a57348510861a2beae0b0ee659badb
|
4
|
+
data.tar.gz: 5a6b26615c07adf981ef46fff9a80c9e4508a9ea
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7ea230f0e82d03ae579845c839dcbadab6e4d19b214916dd8ceb6a10fda8a85783573ec4611e51e5eed71b14e62b2b5c97b4b6d0eb9dd2a32d614ab963887300
|
7
|
+
data.tar.gz: 1161e4498897d8da47ddb7de30cf61f4efc38887b065caf51cf3c3efc7cb642e90aac675142592fa75f821f1926637c38719dbe2619a0f4badb0c8938f7aba06
|
data/bin/mac_shortcuts
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
|
2
|
+
module MacShortcuts
|
3
|
+
require_relative 'mac_shortcuts/version'
|
4
|
+
|
5
|
+
require 'bundler/setup'
|
6
|
+
|
7
|
+
autoload :Shortcut, 'mac_shortcuts/shortcut'
|
8
|
+
autoload :Command, 'mac_shortcuts/command'
|
9
|
+
autoload :ApplicationPreferencesFinder, 'mac_shortcuts/application_preferences_finder'
|
10
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
|
5
|
+
module MacShortcuts
|
6
|
+
class ApplicationPreferencesFinder
|
7
|
+
# @param [String] query
|
8
|
+
#
|
9
|
+
# @return [Array<String>] paths to preferences file
|
10
|
+
#
|
11
|
+
def self.find_with_query(query)
|
12
|
+
founded = Dir[File.join(preferences_path, "*.#{query}.plist")]
|
13
|
+
return founded unless founded.empty?
|
14
|
+
|
15
|
+
apps_dirs_paths = [
|
16
|
+
'/Applications',
|
17
|
+
File.join(Dir.home, 'Applications'),
|
18
|
+
]
|
19
|
+
|
20
|
+
apps_dirs_paths.each do |apps_path|
|
21
|
+
founded = process_apps_paths(Dir[File.join(apps_path, "#{query}.app")])
|
22
|
+
return founded unless founded.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
return founded unless founded.empty?
|
26
|
+
|
27
|
+
# use Spotlight to find applications
|
28
|
+
apps_paths = `mdfind "#{query}.app"`.split("\n")
|
29
|
+
|
30
|
+
# filter out not application results
|
31
|
+
apps_paths.select! do |path|
|
32
|
+
path.end_with?('.app')
|
33
|
+
end
|
34
|
+
|
35
|
+
founded = process_apps_paths(apps_paths)
|
36
|
+
|
37
|
+
founded
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
|
43
|
+
# @return [String] base path for user application preferences
|
44
|
+
#
|
45
|
+
def self.preferences_path
|
46
|
+
@preferences_path ||= File.join(Dir.home, 'Library', 'Preferences')
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param [Array<String>] apps_paths paths to applications folder
|
50
|
+
#
|
51
|
+
# @return [Array<String>] preference paths of input applications
|
52
|
+
#
|
53
|
+
def self.process_apps_paths(apps_paths)
|
54
|
+
apps_paths.map do |app_path|
|
55
|
+
preferences_path_of(app_path)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @param [String] app_path path to application folder
|
60
|
+
#
|
61
|
+
# @return [String] preference path of input application
|
62
|
+
#
|
63
|
+
def self.preferences_path_of(app_path)
|
64
|
+
File.join(preferences_path, "#{self.bundle_identifier_of(app_path)}.plist")
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param [String] app_path path to application folder, example: '/Applications/Messages.app'
|
68
|
+
#
|
69
|
+
# @return [String, nil] bundle identifier of that application
|
70
|
+
#
|
71
|
+
def self.bundle_identifier_of(app_path)
|
72
|
+
plist_path = "#{app_path}/Contents/Info.plist"
|
73
|
+
`/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "#{plist_path}"`.chomp
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'claide'
|
4
|
+
|
5
|
+
module MacShortcuts
|
6
|
+
class PlainInformative < StandardError
|
7
|
+
include CLAide::InformativeError
|
8
|
+
|
9
|
+
def message
|
10
|
+
"[!] #{super}".red
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Command < CLAide::Command
|
15
|
+
require_relative 'command/set'
|
16
|
+
|
17
|
+
self.abstract_command = true
|
18
|
+
self.command = 'mac_shortcuts'
|
19
|
+
self.version = VERSION
|
20
|
+
self.description = 'Command line tool to modify custom shortcuts in Mac applications.'
|
21
|
+
self.plugin_prefixes += %w(mac_shortcuts)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative '../command'
|
4
|
+
|
5
|
+
module MacShortcuts
|
6
|
+
class Set < Command
|
7
|
+
self.summary = 'Set shortcut for application.'
|
8
|
+
self.arguments = [
|
9
|
+
CLAide::Argument.new(%w(APPLICATION PLIST_FILE), true, false),
|
10
|
+
CLAide::Argument.new(%w(MENU_TITLE), true, false),
|
11
|
+
CLAide::Argument.new(%w(SHORTCUT), true, false),
|
12
|
+
]
|
13
|
+
|
14
|
+
def initialize(argv)
|
15
|
+
@application = argv.shift_argument
|
16
|
+
@menu_title = argv.shift_argument
|
17
|
+
@shortcut_str = argv.shift_argument
|
18
|
+
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate!
|
23
|
+
super
|
24
|
+
|
25
|
+
help! 'You must specify APPLICATION or PLIST_FILE' if @application.nil?
|
26
|
+
help! 'You must specify MENU_TITLE' if @menu_title.nil?
|
27
|
+
help! 'You must specify SHORTCUT' if @shortcut_str.nil?
|
28
|
+
|
29
|
+
begin
|
30
|
+
@shortcut = Shortcut.from_pretty(@shortcut_str)
|
31
|
+
rescue Exception => e
|
32
|
+
help! e.message
|
33
|
+
end
|
34
|
+
|
35
|
+
@plist_path = if File.exists?(@application) && File.extname(@application) == '.plist'
|
36
|
+
@application
|
37
|
+
else
|
38
|
+
founded = ApplicationPreferencesFinder.find_with_query(@application)
|
39
|
+
|
40
|
+
help! "Not found location for preferences for query #{@application}" if founded.length == 0
|
41
|
+
help! "Founded too many applications for query #{@application}, results are: #{founded.inspect}" if founded.length != 1
|
42
|
+
|
43
|
+
founded.first
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def run
|
48
|
+
ret = system(%{defaults write "#{@plist_path}" NSUserKeyEquivalents -dict-add "#{@menu_title}" -string "#{@shortcut.to_code}"})
|
49
|
+
unless ret
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
|
53
|
+
puts 'Shortcut was set, now restart application to take effect.'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
|
2
|
+
module MacShortcuts
|
3
|
+
class Shortcut
|
4
|
+
attr_accessor :command
|
5
|
+
attr_accessor :shift
|
6
|
+
attr_accessor :control
|
7
|
+
attr_accessor :alt
|
8
|
+
attr_accessor :key
|
9
|
+
|
10
|
+
PRETTY_MAP = {
|
11
|
+
command: %w(⌘ @ cmd command),
|
12
|
+
alt: %w(⌥ ~ alt option),
|
13
|
+
shift: %w(⇧ $ shift),
|
14
|
+
control: %w(^ ^ ctrl control),
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
CODE_MAP = PRETTY_MAP.map { |key, values|
|
18
|
+
[key, values[1]]
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
KEYS_MAP = {
|
22
|
+
'→' => 'right',
|
23
|
+
'←' => 'left',
|
24
|
+
}
|
25
|
+
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
@command = @shift = @control = @alt = false
|
29
|
+
@key = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# @param [String] shortcut_str
|
34
|
+
#
|
35
|
+
def self.from_code(shortcut_str)
|
36
|
+
inst = self.new
|
37
|
+
CODE_MAP.each do |key, value|
|
38
|
+
inst.send("#{key}=", shortcut_str.include?(value))
|
39
|
+
end
|
40
|
+
inst.key = shortcut_str[-1]
|
41
|
+
inst
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param [String] shortcut_str
|
45
|
+
#
|
46
|
+
def self.from_pretty(shortcut_str)
|
47
|
+
inst = self.new
|
48
|
+
components = components_from_pretty(shortcut_str)
|
49
|
+
components.each do |cmp|
|
50
|
+
case cmp
|
51
|
+
when String
|
52
|
+
inst.key = cmp
|
53
|
+
when Symbol
|
54
|
+
inst.send("#{cmp}=", true)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
inst
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
components = []
|
63
|
+
PRETTY_MAP.each do |key, value|
|
64
|
+
components << value.first if self.send(key)
|
65
|
+
end
|
66
|
+
components << @key if @key
|
67
|
+
components.join(' + ')
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_code
|
71
|
+
components = []
|
72
|
+
CODE_MAP.each do |key, value|
|
73
|
+
components << value if self.send(key)
|
74
|
+
end
|
75
|
+
components << @key if @key
|
76
|
+
components.join
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @param cmp [String]
|
82
|
+
#
|
83
|
+
# @return [Symbol, nil]
|
84
|
+
#
|
85
|
+
def self.key_for_pretty(cmp)
|
86
|
+
key = nil
|
87
|
+
PRETTY_MAP.each do |curr_key, values|
|
88
|
+
if values.include?(cmp)
|
89
|
+
key = curr_key
|
90
|
+
break
|
91
|
+
end
|
92
|
+
end
|
93
|
+
key
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param str [String]
|
97
|
+
#
|
98
|
+
# @return [Array<Symbol, String>]
|
99
|
+
#
|
100
|
+
def self.components_from_pretty(str)
|
101
|
+
components = str.split(/( |\+)/)
|
102
|
+
components.reject! { |cmp| cmp.strip.empty? }
|
103
|
+
components.reject! { |cmp| cmp == '+' }
|
104
|
+
last = components.pop
|
105
|
+
|
106
|
+
correct_last = KEYS_MAP[last] || last
|
107
|
+
|
108
|
+
components.map! do |cmp|
|
109
|
+
key = key_for_pretty(cmp)
|
110
|
+
if key.nil?
|
111
|
+
raise "Unknown text for #{cmp}"
|
112
|
+
end
|
113
|
+
key
|
114
|
+
end
|
115
|
+
components + [correct_last]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'mac_shortcuts/version'
|
7
|
+
|
8
|
+
|
9
|
+
Gem::Specification.new do |s|
|
10
|
+
s.name = 'mac_shortcuts'
|
11
|
+
s.version = MacShortcuts::VERSION
|
12
|
+
s.date = Date.today
|
13
|
+
s.summary = 'Command line tool to modify custom shortcuts in Mac applications.'
|
14
|
+
s.description = "Command line tool to modify custom shortcuts in Mac applications.\n"
|
15
|
+
'For now just adding.'
|
16
|
+
s.authors = ['Roman Kříž']
|
17
|
+
s.email = 'roman@kriz.io'
|
18
|
+
|
19
|
+
s.homepage = 'https://github.com/samnung/rb-mac_shortcuts'
|
20
|
+
s.license = 'MIT'
|
21
|
+
|
22
|
+
s.files = Dir['bin/**/*'] + Dir['lib/**/*'] + ["#{s.name}.gemspec"]
|
23
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
24
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
25
|
+
|
26
|
+
s.add_runtime_dependency 'claide', '~> 0.8'
|
27
|
+
|
28
|
+
s.add_development_dependency 'bundler', '~> 1.3'
|
29
|
+
s.add_development_dependency 'rspec', '~> 3.2'
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mac_shortcuts
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roman Kříž
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: claide
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.2'
|
55
|
+
description: 'Command line tool to modify custom shortcuts in Mac applications.
|
56
|
+
|
57
|
+
'
|
58
|
+
email: roman@kriz.io
|
59
|
+
executables:
|
60
|
+
- mac_shortcuts
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- bin/mac_shortcuts
|
65
|
+
- lib/mac_shortcuts.rb
|
66
|
+
- lib/mac_shortcuts/application_preferences_finder.rb
|
67
|
+
- lib/mac_shortcuts/command.rb
|
68
|
+
- lib/mac_shortcuts/command/set.rb
|
69
|
+
- lib/mac_shortcuts/shortcut.rb
|
70
|
+
- lib/mac_shortcuts/version.rb
|
71
|
+
- mac_shortcuts.gemspec
|
72
|
+
homepage: https://github.com/samnung/rb-mac_shortcuts
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.4.6
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Command line tool to modify custom shortcuts in Mac applications.
|
96
|
+
test_files: []
|