mac_shortcuts 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ lib = File.expand_path('../lib', File.dirname(__FILE__))
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+
7
+ require 'mac_shortcuts'
8
+
9
+ MacShortcuts::Command.run(ARGV)
@@ -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,4 @@
1
+
2
+ module MacShortcuts
3
+ VERSION = '0.1'
4
+ 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: []