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.
@@ -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: []