plister 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ff894223164c3b13e6fe143912b533c2b629bab0
4
+ data.tar.gz: 09848e3721c574e6997cb2363c1524cb8a13b7d2
5
+ SHA512:
6
+ metadata.gz: 840ff9a88f9518500b0d820ebb41c84c8739bb91aa0351ac689823ea5e11aad12ba5dd3b7cd9fc3a0413a44ecbbf354e63147bb4ea4d65fcd42de8d22f908b08
7
+ data.tar.gz: 965a450fa0c8c86212d26ce672391420ca5d118a0662245aac253347e2ac8484c558944213e3d5868d1c0787351d7e4d52f7e6f16d1906858f55a9700d49d54f
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ Metrics/LineLength:
2
+ Enabled: false
3
+
4
+ Style/Documentation:
5
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
5
+ cache: bundler
6
+ sudo: false
7
+ script: script/cibuild
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in plister.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Ben Balter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # Plister
2
+
3
+ *A utility for programmatically setting OS X plist file preferences*
4
+
5
+ ## What it does
6
+
7
+ Most dotfile setups have a string of cryptic `defaults write com.apple...`-type commands. Plister simplifies that process by allowing you to store your OS X preferences in a single YAML file (likily in your home directory or within your dotfiles repostiory), and exposes a single `plister` command line tool to set your saved preferences.
8
+
9
+ ## Usage
10
+
11
+ 1. Install the Gem (`gem install plister`)
12
+ 2. Create a preference file as `~/.osx.yml` (see below)
13
+ 3. Run `plister` command to set the desired preferences
14
+
15
+ ### The command line tool
16
+
17
+ `$ plister [path-to-your-preferences.yml]`
18
+
19
+ If no preference file is passed, Plister will default to `~/.osx.yml`.
20
+
21
+ ### Creating a preference file
22
+
23
+ 1. Create a file in your home directory called `.osx.yml` (or symlink it from elsewhere)
24
+ .
25
+ 2. Add your OS X preferences to the `.osx.yml` file, following the instructions below.
26
+
27
+ ### Describing preferences
28
+
29
+ OS X has several different ways of storing preferences, each with their own domain (e.g., `com.apple.safari`). If you're copying your preferences from a tutorial or someone else's dotfiles, you can tell the domain and type by the command used to set it.
30
+
31
+ ```
32
+ defaults write -someFlag com.apple.safari key value
33
+ COMMAND FLAG DOMAIN SETTING
34
+ ```
35
+
36
+ #### User preferences
37
+
38
+ User preferences are specific to a user and live in `~/Library/Preferences`. They are the default and have no flag. Example: `defaults write com.apple.safari someSetting -int 0`.
39
+
40
+ #### System preferences
41
+
42
+ System preferences are system wide and live in `/Library/Preferenences`. These are often passed as absolute paths, and require `sudo`. Example: `sudo defaults write /Library/Preferences/com.apple.safari.plist someSetting -int 0`.
43
+
44
+ #### Global preferences
45
+
46
+ Global preferences are not application specific and have a domain of `NSGlobalDomain`. This may be omitted in favor of the `-g` or `-globalDomain` flag. Global preference can be either user or system preferences and should be stored with a key of `.GlobalPreferences` in your config file. Example: `defaults write NSGlobalDomain someSetting -int 0`.
47
+
48
+ #### Host preferences
49
+
50
+ Host preferences live in `~/Library/Preferences/byHost` and are identified by the `-currentHost` flag. Example: `defaults write -currentHost com.apple.safari someSetting -int 0`.
51
+
52
+ ### The `.osx.yml` file
53
+
54
+ Settings are group by type and domain within your `.osx.yml` file.
55
+
56
+ ```yml
57
+ user:
58
+ com.apple.safari:
59
+ someSetting: 0
60
+ anotherSetting: my-value
61
+
62
+ com.apple.dock:
63
+ autohide: true
64
+
65
+ # NSGlobalDomain preferences
66
+ .GlobalPreferences:
67
+ WebKitDeveloperExtras: true
68
+
69
+ system:
70
+ com.apple.SoftwareUpdate:
71
+ AutomaticCheckEnabled: true
72
+
73
+ host:
74
+ com.apple.ScreenSaver.iLifeSlideShows:
75
+ styleKey: VintagePrints
76
+ ```
77
+
78
+ The above would be equivalent to:
79
+
80
+ ```
81
+ defaults write com.apple.safari someSetting -int 0
82
+ defaults write com.apple.safari anotherSetting my-value
83
+ defaults write com.apple.dock autohide -bool true
84
+ defaults write NSGlobalDomain WebKitDeveloperExtras -bool true
85
+ sudo defaults write com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true
86
+ default write -currentHost com.apple.ScreenSaver.iLifeSlideShows styleKey VintagePrints
87
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/plister ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/plister'
4
+
5
+ preferences = Plister.preferences(ARGV[0])
6
+
7
+ puts "Using preference file #{preferences.path}"
8
+ puts "Found preferences for #{preferences.domains.count} applications"
9
+
10
+ preferences.set!(verbose: true)
11
+
12
+ puts 'Preferences set!'
@@ -0,0 +1,68 @@
1
+ module Plister
2
+ class Plist
3
+ attr_accessor :domain, :type
4
+ TYPES = %w(user system host).freeze
5
+
6
+ def initialize(domain, type: 'user')
7
+ @domain = domain
8
+ @type = type.to_s
9
+ fail ArgumentError, 'Invalid type' unless valid_type?
10
+ end
11
+
12
+ def preferences
13
+ @preferences ||= CFPropertyList.native_types(list.value)
14
+ end
15
+
16
+ def preferences=(prefs)
17
+ list.value = CFPropertyList.guess(prefs, convert_unknown_to_string: true)
18
+ @preferenes = nil
19
+ preferences
20
+ end
21
+
22
+ def merge(prefs)
23
+ self.preferences = preferences.deep_merge(prefs)
24
+ end
25
+
26
+ def write
27
+ fail IOError, "#{path} is not writable by #{Plister.user}" unless writable?
28
+ list.save
29
+ end
30
+
31
+ private
32
+
33
+ def path
34
+ @path ||= begin
35
+ case type
36
+ when 'system'
37
+ "/Library/Preferences/#{domain}.plist"
38
+ when 'user'
39
+ "/Users/#{Plister.user}/Library/Preferences/#{domain}.plist"
40
+ when 'host'
41
+ "/Users/#{Plister.user}/Library/preferences/ByHost/#{domain}.#{Plister.uuid}.plist"
42
+ end
43
+ end
44
+ end
45
+
46
+ def list
47
+ fail IOError, "#{path} does not exist" unless exists?
48
+ fail IOError, "#{path} is not readable by #{Plister.user}" unless readable?
49
+ @list ||= CFPropertyList::List.new file: path
50
+ end
51
+
52
+ def exists?
53
+ File.exist?(path)
54
+ end
55
+
56
+ def writable?
57
+ File.writable?(path)
58
+ end
59
+
60
+ def readable?
61
+ File.readable?(path)
62
+ end
63
+
64
+ def valid_type?
65
+ TYPES.include?(type)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ module Plister
2
+ class Preferences
3
+ attr_reader :path
4
+
5
+ def initialize(path = nil)
6
+ @path = path || "/Users/#{Plister.user}/.osx.yml"
7
+ end
8
+
9
+ def set!(verbose: false)
10
+ data.each do |type, domains|
11
+ domains.each do |domain, prefs|
12
+ puts "Setting #{type} preferences for #{domain}" if verbose
13
+ plist = Plist.new(domain, type: type)
14
+ plist.merge(prefs)
15
+ plist.write
16
+ end
17
+ end
18
+ end
19
+
20
+ def domains
21
+ @domains ||= data.map { |_k, v| v.keys }.flatten
22
+ end
23
+
24
+ private
25
+
26
+ def data
27
+ @data ||= YAML.load(contents)
28
+ end
29
+
30
+ def contents
31
+ @contents ||= File.open(path).read
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module Plister
3
+ VERSION = '0.1.0'.freeze
4
+ end
data/lib/plister.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'CFPropertyList'
2
+ require 'deep_merge'
3
+ require 'yaml'
4
+
5
+ require_relative 'plister/version'
6
+ require_relative 'plister/plist'
7
+ require_relative 'plister/preferences'
8
+
9
+ module Plister
10
+ class << self
11
+ def preferences(path = nil)
12
+ Plister::Preferences.new(path)
13
+ end
14
+
15
+ def user
16
+ @user ||= `logname`.strip
17
+ end
18
+
19
+ def uuid
20
+ @uuid ||= begin
21
+ uuid = `ioreg -rd1 -c IOPlatformExpertDevice`
22
+ matches = uuid.match(/"IOPlatformUUID" = "([0-9A-F-]{36})"/)
23
+ matches[1] if matches
24
+ end
25
+ end
26
+ end
27
+ end
data/plister.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'plister/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'plister'
8
+ spec.version = Plister::VERSION
9
+ spec.authors = ['Ben Balter']
10
+ spec.email = ['ben.balter@github.com']
11
+
12
+ spec.summary = 'A utility for programmatically setting OS X plist file preferences'
13
+ spec.homepage = 'https://github.com/benbalter/plister'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'bin'
18
+
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_dependency 'CFPropertyList', '~> 2.3'
23
+ spec.add_dependency 'deep_merge', '~> 1.0'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.11'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rspec', '~> 3.0'
28
+ spec.add_development_dependency 'pry', '~> 0.10'
29
+ spec.add_development_dependency 'rubocop', '~> 0.36'
30
+ end
data/script/bootstrap ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
data/script/cibuild ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ set -ex
4
+
5
+ bundle exec rake spec
6
+ bundle exec rubocop
7
+ bundle exec gem build plister.gemspec
data/script/console ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'plister'
5
+ require 'pry'
6
+ Pry.start
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: plister
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Balter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: CFPropertyList
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: deep_merge
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.11'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.10'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.10'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.36'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.36'
111
+ description:
112
+ email:
113
+ - ben.balter@github.com
114
+ executables:
115
+ - plister
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".rubocop.yml"
122
+ - ".travis.yml"
123
+ - Gemfile
124
+ - LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - bin/plister
128
+ - lib/plister.rb
129
+ - lib/plister/plist.rb
130
+ - lib/plister/preferences.rb
131
+ - lib/plister/version.rb
132
+ - plister.gemspec
133
+ - script/bootstrap
134
+ - script/cibuild
135
+ - script/console
136
+ homepage: https://github.com/benbalter/plister
137
+ licenses:
138
+ - MIT
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.5.1
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: A utility for programmatically setting OS X plist file preferences
160
+ test_files: []
161
+ has_rdoc: