geoffrey 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +33 -0
- data/README.md +116 -0
- data/Rakefile +7 -0
- data/geoffrey.gemspec +26 -0
- data/lib/geoffrey.rb +23 -0
- data/lib/geoffrey/package.rb +108 -0
- data/lib/geoffrey/plist.rb +56 -0
- data/lib/geoffrey/template.rb +30 -0
- data/lib/geoffrey/version.rb +3 -0
- data/spec/package_spec.rb +64 -0
- data/spec/plist_spec.rb +75 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/static/example.plist +0 -0
- data/spec/static/test.tar.gz +0 -0
- data/spec/static/test.tgz +0 -0
- data/spec/static/test.txt.gz +0 -0
- data/spec/static/test.txt.zip +0 -0
- data/spec/template_spec.rb +26 -0
- metadata +193 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
geoffrey (0.0.0)
|
5
|
+
plist4r
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
awesome_print (0.2.1)
|
11
|
+
haml (3.0.17)
|
12
|
+
libxml-ruby (1.1.4)
|
13
|
+
libxml4r (0.2.6)
|
14
|
+
libxml-ruby (>= 1.1.3)
|
15
|
+
mocha (0.9.8)
|
16
|
+
rake
|
17
|
+
plist4r (1.1.1)
|
18
|
+
haml
|
19
|
+
libxml-ruby
|
20
|
+
libxml4r
|
21
|
+
rake (0.8.7)
|
22
|
+
rspec (1.3.0)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
awesome_print
|
29
|
+
bundler (~> 1.0.0.rc.5)
|
30
|
+
geoffrey!
|
31
|
+
mocha (= 0.9.8)
|
32
|
+
plist4r
|
33
|
+
rspec (= 1.3.0)
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
geoffrey
|
2
|
+
========
|
3
|
+
|
4
|
+
## ALERT!
|
5
|
+
|
6
|
+
This is very early alpha code, use with precaution. It's a spinoff of myself willing to
|
7
|
+
improve my [dotfiles project](http://github.com/albertllop/dotfiles) a step further. All
|
8
|
+
code examples in this README come from it.
|
9
|
+
|
10
|
+
## Introduction
|
11
|
+
|
12
|
+
Geoffrey's your little helper, that who just wants to makes your life easier.
|
13
|
+
|
14
|
+
It aims to help you create little scripts to setup your OSX the way you like.
|
15
|
+
If, like me, you use different computers at work, home, or even when travelling,
|
16
|
+
you'll know it's a pain in the ass to keep everything up to date.
|
17
|
+
|
18
|
+
Inspired in the numerous dotfiles projects, specially
|
19
|
+
[holman's](http://github.com/holman/dotfiles),
|
20
|
+
the intention is to bring customization to a bigger extend.
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
$ [sudo] gem install geoffrey
|
25
|
+
|
26
|
+
Geoffrey's Talents
|
27
|
+
==================
|
28
|
+
|
29
|
+
Geoffrey has many talents, and thus you'll find he can help you in one of these areas:
|
30
|
+
|
31
|
+
## Packages
|
32
|
+
|
33
|
+
If you ever used [Ciarán Walsh's](http://ciaranwal.sh) SIMBL plugins, you'll remember
|
34
|
+
what a pain it is to install them every time. Now you can do so with the next piece of code:
|
35
|
+
|
36
|
+
require 'geoffrey'
|
37
|
+
Geoffrey.package do
|
38
|
+
url 'http://www.culater.net/dl/files/SIMBL-0.9.7a.zip'
|
39
|
+
options :sudo => true, :unless => Proc.new{ File.exists?("/Library/LaunchAgents/net.culater.SIMBL.Agent.plist") }
|
40
|
+
end
|
41
|
+
|
42
|
+
Geoffrey will take care of downloading the zip file, and install whatever .pkg
|
43
|
+
file is in the zip. The possible options are:
|
44
|
+
|
45
|
+
* `:sudo` => in case it needs to be executed as sudo to install (it does if the installer would ever ask for your password)
|
46
|
+
* `:unless` => in order to make running this idempotent.
|
47
|
+
* `:file` => specify which of the files contained in the zip has to be installed. If it's not specified it uses the first .pkg it finds.
|
48
|
+
|
49
|
+
With that you'll have SIMBL installed and working. Now suppose you want to install a bundle.
|
50
|
+
You'd have to download a file, and move it to a directory. Geoffrey can help you a little,
|
51
|
+
basically downloading and uncompressing the zip, and you just have to define the install
|
52
|
+
method.
|
53
|
+
|
54
|
+
require 'geoffrey'
|
55
|
+
Geoffrey.package do
|
56
|
+
url "http://github.com/dabeeeenster/terminaltabswitching/raw/master/TerminalTabSwitching.bundle.zip"
|
57
|
+
options :file => "TerminalTabSwitching.bundle"
|
58
|
+
|
59
|
+
def install
|
60
|
+
plugins_dir = "#{ENV["HOME"]}/Library/Application Support/SIMBL/Plugins"
|
61
|
+
FileUtils.mkdir_p plugins_dir
|
62
|
+
FileUtils.mv file_to_install, plugins_dir, :force => true
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
`file_to_install` is provided by geoffrey poiting to the automatically downloaded/uncompressed file.
|
68
|
+
|
69
|
+
## Application Configuration
|
70
|
+
|
71
|
+
Everything in OSX seems to work around `.plist` files. This takes a little bit of work to figure out,
|
72
|
+
but once you do, you can have your favourite apps the way you like. This is my script to get Terminal.app
|
73
|
+
up and running with Pro scheme, Menlo Font 14pt, and a size 520x100.
|
74
|
+
|
75
|
+
require 'geoffrey'
|
76
|
+
|
77
|
+
Geoffrey.plist do
|
78
|
+
file :terminal
|
79
|
+
affects "/Applications/Utilities/Terminal.app"
|
80
|
+
|
81
|
+
options["Default Window Settings"] = "Pro"
|
82
|
+
options["Startup Window Settings"] = "Pro"
|
83
|
+
options["HasMigratedDefaults"] = true
|
84
|
+
options["Window Settings"]["Pro"]["Font"] = "bplist00\xD4\x01\x02\x03\x04\x05\x06\x18\x19X$versionX$objectsY$archiverT$top\x12\x00\x01\x86\xA0\xA4\a\b\x11\x12U$null\xD4\t\n\v\f\r\x0E\x0F\x10V$classVNSNameVNSSizeXNSfFlags\x80\x03\x80\x02\#@,\x00\x00\x00\x00\x00\x00\x10\x10]Menlo-Regular\xD2\x13\x14\x15\x16Z$classnameX$classesVNSFont\xA2\x15\x17XNSObject_\x10\x0FNSKeyedArchiver\xD1\x1A\eTroot\x80\x01\b\x11\x1A#-27<BKRY`ikmvx\x86\x8B\x96\x9F\xA6\xA9\xB2\xC4\xC7\xCC\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x1C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xCE"
|
85
|
+
options["Window Settings"]["Pro"]["Font"].blob = true
|
86
|
+
options["Window Settings"]["Pro"]["columnCount"] = 520
|
87
|
+
options["Window Settings"]["Pro"]["rowCount"] = 100
|
88
|
+
end
|
89
|
+
|
90
|
+
* `file` => Geoffrey knows of a few files in your system you can specify with symbols. If you want to work with a different one, just write the full path.
|
91
|
+
* `affects` => When you close Terminal.app, it'll dump its otions into the plist. So you have to stop it, change the plist file, then reopen it. Geoffrey does this automatically if you tell him what must be rebooted.
|
92
|
+
* `options` => Its the plist has per se. Using the fantastic [plist4r](http://github.com/dreamcat4/plist4r) gem, you can modify it.
|
93
|
+
|
94
|
+
You might have seen something peculiar:
|
95
|
+
|
96
|
+
options["Window Settings"]["Pro"]["Font"].blob = true
|
97
|
+
|
98
|
+
Some values in plist files are of type "Data", which is just binary stuff. Plist4r handles
|
99
|
+
these as strings with a special flag.
|
100
|
+
|
101
|
+
The best way to know what to put in every value, is to just go to the file and take a
|
102
|
+
look. They all tend to make sense. For data values, however, you might have more work. The
|
103
|
+
way I do it is opening the file with Plist4r, and reading the value:
|
104
|
+
|
105
|
+
require 'plist4r'
|
106
|
+
plist = Plist4r.open("the/file.plist")
|
107
|
+
plist["whatever"]["option"] # => copy whatever it returns
|
108
|
+
|
109
|
+
Just make sure that when you set it in your geoffrey you put the flag blog true. Otherwise you might see some really weird system errors.
|
110
|
+
|
111
|
+
## A few words
|
112
|
+
|
113
|
+
This is work done in my free hours, it's not yet finished. The code is dirty and mainly undocumented. It all started on #whyday,
|
114
|
+
but I'm so lazy that I've needed a lot of time to do just this.
|
115
|
+
|
116
|
+
Thanks!
|
data/Rakefile
ADDED
data/geoffrey.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
3
|
+
require 'geoffrey/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "geoffrey"
|
7
|
+
s.version = Geoffrey::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Albert Llop"]
|
10
|
+
s.email = ["mrsimo@gmail.com"]
|
11
|
+
s.summary = "Geoffrey is a little helper to aid in the installation of packages and configuration of various Mac OSX applications."
|
12
|
+
s.description = File.read(File.dirname(__FILE__) + "/README.md")
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "geoffrey"
|
16
|
+
|
17
|
+
s.add_development_dependency "bundler", "~> 1.0.0.rc.5"
|
18
|
+
s.add_development_dependency "rspec", "~> 1.3.0"
|
19
|
+
s.add_development_dependency "mocha", "~> 0.9.8"
|
20
|
+
|
21
|
+
s.add_dependency 'plist4r'
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.executables = `git ls-files`.split("\n").select{|f| f =~ /^bin/}
|
25
|
+
s.require_path = 'lib'
|
26
|
+
end
|
data/lib/geoffrey.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'geoffrey/package'
|
2
|
+
require 'geoffrey/plist'
|
3
|
+
|
4
|
+
module Geoffrey
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def package(&block)
|
9
|
+
package = Package.new
|
10
|
+
package.instance_eval &block
|
11
|
+
package.download_and_decompress
|
12
|
+
package.install
|
13
|
+
end
|
14
|
+
|
15
|
+
def plist(&block)
|
16
|
+
plist = Plist.new
|
17
|
+
plist.instance_eval &block
|
18
|
+
plist.save
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Geoffrey
|
7
|
+
class Package
|
8
|
+
attr_accessor :url, :options, :format, :filename, :dir
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@options = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def url(val = nil)
|
15
|
+
@url = val if val
|
16
|
+
@url
|
17
|
+
end
|
18
|
+
|
19
|
+
def options(val = nil)
|
20
|
+
@options = val if val
|
21
|
+
@options
|
22
|
+
end
|
23
|
+
|
24
|
+
def download_and_decompress
|
25
|
+
return nil if shouldnt_install
|
26
|
+
|
27
|
+
@filename = @url.split("/").last
|
28
|
+
unless @url.nil?
|
29
|
+
get_format
|
30
|
+
|
31
|
+
file = Tempfile.new("geoffrey")
|
32
|
+
file.write open(@url).read
|
33
|
+
file.close
|
34
|
+
|
35
|
+
@dir = "#{Dir.tmpdir}/#{filename}"
|
36
|
+
FileUtils.rm_rf @dir if File.exist?(@dir)
|
37
|
+
FileUtils.mkdir_p @dir
|
38
|
+
|
39
|
+
decompress file, @dir
|
40
|
+
|
41
|
+
@dir
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def install
|
46
|
+
return nil if shouldnt_install
|
47
|
+
|
48
|
+
command = case File.extname file_to_install
|
49
|
+
when ".pkg"
|
50
|
+
"installer -pkg #{file_to_install} -target /"
|
51
|
+
end
|
52
|
+
execute command
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def shouldnt_install
|
58
|
+
@options[:unless] && @options[:unless].respond_to?(:call) && @options[:unless].call
|
59
|
+
end
|
60
|
+
|
61
|
+
def execute(command, options = {})
|
62
|
+
options = @options.merge(options)
|
63
|
+
command = "sudo #{command}" if options[:sudo]
|
64
|
+
puts "Executing: #{command}" if $verbose
|
65
|
+
system command
|
66
|
+
end
|
67
|
+
|
68
|
+
# If it was specified through options, then get that, otherwise
|
69
|
+
# get the first file with .pkg extension
|
70
|
+
def file_to_install
|
71
|
+
if @options[:file]
|
72
|
+
"#{@dir}/#{@options[:file]}"
|
73
|
+
else
|
74
|
+
files = Dir.glob("#{@dir}/**/*.pkg")
|
75
|
+
files.first
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_format
|
80
|
+
@format = case File.extname @url
|
81
|
+
when '.zip' then :zip
|
82
|
+
when '.tar' then :tar
|
83
|
+
when '.tgz' then :tgz
|
84
|
+
when '.gz'
|
85
|
+
if @filename =~ /\.tar\.gz/
|
86
|
+
:tgz
|
87
|
+
else
|
88
|
+
:gz
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def decompress(file,target)
|
94
|
+
command = case @format
|
95
|
+
when :zip
|
96
|
+
"unzip -o #{file.path} -d #{target} 1> /dev/null"
|
97
|
+
when :tar
|
98
|
+
"tar xf #{file.path} -C #{target}"
|
99
|
+
when :tgz
|
100
|
+
"tar xzf #{file.path} -C #{target}"
|
101
|
+
when :gz
|
102
|
+
"cp #{file.path} #{target}/#{filename}.gz; gunzip #{target}/*"
|
103
|
+
end
|
104
|
+
execute command, :sudo => false
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'plist4r'
|
2
|
+
|
3
|
+
module Geoffrey
|
4
|
+
class Plist
|
5
|
+
|
6
|
+
FILES = {
|
7
|
+
:textmate => "#{ENV["HOME"]}/Library/Preferences/com.macromates.textmate.plist",
|
8
|
+
:terminal => "#{ENV["HOME"]}/Library/Preferences/com.apple.Terminal.plist"
|
9
|
+
}
|
10
|
+
|
11
|
+
attr_accessor :data, :file, :process
|
12
|
+
|
13
|
+
def file(file = nil)
|
14
|
+
if file
|
15
|
+
file = FILES[file] if Symbol === file
|
16
|
+
raise "File #{file} not found" if file.nil? || !File.exists?(file)
|
17
|
+
@data = Plist4r.open(file)
|
18
|
+
@file = file
|
19
|
+
end
|
20
|
+
@file
|
21
|
+
end
|
22
|
+
|
23
|
+
def affects(value)
|
24
|
+
@process = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def options
|
28
|
+
data
|
29
|
+
end
|
30
|
+
|
31
|
+
def [](key)
|
32
|
+
data[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def []=(key,value)
|
36
|
+
data[key] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
def save
|
40
|
+
kill
|
41
|
+
data.save
|
42
|
+
open
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def kill
|
48
|
+
system "killall '#{@process}'" unless @process.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def open
|
52
|
+
system "open '#{@process}'" unless @process.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Geoffrey
|
2
|
+
class Template
|
3
|
+
|
4
|
+
attr_accessor :title, :description
|
5
|
+
|
6
|
+
def self.inherited(subclass)
|
7
|
+
@@subclasses ||= []
|
8
|
+
@@subclasses << subclass
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def self.attr_rw(*attrs)
|
13
|
+
attrs.each do |attr|
|
14
|
+
class_eval %Q{
|
15
|
+
def #{attr}(val=nil)
|
16
|
+
val.nil? ? @#{attr} : @#{attr} = val
|
17
|
+
end
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_rw :title, :description
|
23
|
+
|
24
|
+
def all
|
25
|
+
@@subclasses
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'geoffrey/package'
|
3
|
+
|
4
|
+
describe Geoffrey::Package do
|
5
|
+
it "allows for the url to be specified" do
|
6
|
+
package = Geoffrey::Package.new
|
7
|
+
package.url 'http://localhost/crappy.zip'
|
8
|
+
package.url.should == 'http://localhost/crappy.zip'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "allows for some options to be specified" do
|
12
|
+
package = Geoffrey::Package.new
|
13
|
+
package.options :yes => "no"
|
14
|
+
package.options.should == {:yes => "no"}
|
15
|
+
end
|
16
|
+
|
17
|
+
context "package installation" do
|
18
|
+
|
19
|
+
it "installs basic package stuff" do
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
it "doesnt install the thing if a :unless option is provided" do
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
it "inverse if passed a :if option" do
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'package downloading/unzipping' do
|
34
|
+
# Things should be uncompressed into a temporary folder, and the
|
35
|
+
# method should return where it is.
|
36
|
+
|
37
|
+
it "smartly unzips the file if it's a zip" do
|
38
|
+
package = Geoffrey::Package.new
|
39
|
+
package.url(File.dirname(__FILE__) + "/static/test.txt.zip")
|
40
|
+
dir = package.download_and_decompress
|
41
|
+
files = Dir.glob("#{dir}/*")
|
42
|
+
files.size.should == 1
|
43
|
+
files.last.split("/").last.should == "test.txt"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "smartly untars the tar if it's a tar" do
|
47
|
+
package = Geoffrey::Package.new
|
48
|
+
package.url(File.dirname(__FILE__) + "/static/test.tar.gz")
|
49
|
+
dir = package.download_and_decompress
|
50
|
+
files = Dir.glob("#{dir}/*")
|
51
|
+
files.size.should == 1
|
52
|
+
files.last.split("/").last.should == "test.txt"
|
53
|
+
end
|
54
|
+
|
55
|
+
# it "smartly ungzips if its a gzip" do
|
56
|
+
# package = Geoffrey::Package.new
|
57
|
+
# package.url(File.dirname(__FILE__) + "/static/test.txt.gz")
|
58
|
+
# dir = package.download_and_decompress
|
59
|
+
# files = Dir.glob("#{dir}/*")
|
60
|
+
# files.size.should == 1
|
61
|
+
# files.last.split("/").last.should == "test.txt"
|
62
|
+
# end
|
63
|
+
end
|
64
|
+
end
|
data/spec/plist_spec.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'geoffrey/plist'
|
3
|
+
|
4
|
+
describe Geoffrey::Plist do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
# To be able to play with the file we copy it every time
|
8
|
+
@plist_file = Tempfile.new 'plist_spec'
|
9
|
+
@plist_file.write File.read(File.dirname(__FILE__) + "/static/example.plist")
|
10
|
+
@plist_file.close
|
11
|
+
end
|
12
|
+
|
13
|
+
it "raises an error if the file passed doesn't exist" do
|
14
|
+
lambda{ Geoffrey::Plist.new.file("it/surely/doesnt/exist") }.should raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it "also accepts symbol values for already known values" do
|
18
|
+
plist = Geoffrey::Plist.new
|
19
|
+
plist.file :terminal
|
20
|
+
plist.file.should include("com.apple.Terminal.plist")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "parses correct plist items" do
|
24
|
+
plist = Geoffrey::Plist.new
|
25
|
+
plist.file(@plist_file.path)
|
26
|
+
plist.data.class.should == Plist4r::Plist
|
27
|
+
end
|
28
|
+
|
29
|
+
it "knows that it has to close some appication before applying changes" do
|
30
|
+
plist = Geoffrey::Plist.new
|
31
|
+
plist.file(@plist_file.path)
|
32
|
+
plist.affects "/some/process"
|
33
|
+
|
34
|
+
# Since I don't know how to test this without starting and shutting down processes
|
35
|
+
# I'll just suppose that some internal functions are called
|
36
|
+
plist.expects(:system).twice
|
37
|
+
plist.save
|
38
|
+
end
|
39
|
+
|
40
|
+
context "plist modification" do
|
41
|
+
it "allows adding new plist item" do
|
42
|
+
plist = Geoffrey::Plist.new
|
43
|
+
plist.file(@plist_file.path)
|
44
|
+
plist['surely_a_new_key'] = "Hello"
|
45
|
+
plist.save
|
46
|
+
|
47
|
+
plist = Geoffrey::Plist.new
|
48
|
+
plist.file(@plist_file.path)
|
49
|
+
plist['surely_a_new_key'].should == "Hello"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "allows modifying existing keys" do
|
53
|
+
plist = Geoffrey::Plist.new
|
54
|
+
plist.file(@plist_file.path)
|
55
|
+
existing_key = plist.data.keys.first
|
56
|
+
plist[existing_key] = "New value"
|
57
|
+
plist.save
|
58
|
+
|
59
|
+
plist = Geoffrey::Plist.new
|
60
|
+
plist.file(@plist_file.path)
|
61
|
+
plist[existing_key].should == "New value"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "can also be accessed through options" do
|
65
|
+
plist = Geoffrey::Plist.new
|
66
|
+
plist.file(@plist_file.path)
|
67
|
+
plist.options['surely_a_new_key'] = "Hello"
|
68
|
+
plist.save
|
69
|
+
|
70
|
+
plist = Geoffrey::Plist.new
|
71
|
+
plist.file(@plist_file.path)
|
72
|
+
plist.options['surely_a_new_key'].should == "Hello"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'geoffrey/template'
|
3
|
+
|
4
|
+
class SimpleTest < Geoffrey::Template
|
5
|
+
title "Simple template test"
|
6
|
+
description "It does really nice stuff"
|
7
|
+
end
|
8
|
+
|
9
|
+
class ExtraTest < Geoffrey::Template
|
10
|
+
title "A more advanced test"
|
11
|
+
description "It does even nicer stuff"
|
12
|
+
end
|
13
|
+
|
14
|
+
describe Geoffrey::Template do
|
15
|
+
|
16
|
+
it "globally knows of all the described templates" do
|
17
|
+
Geoffrey::Template.all.should == [SimpleTest, ExtraTest]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "provides a basic way to describe actions" do
|
21
|
+
SimpleTest.title.should == "Simple template test"
|
22
|
+
ExtraTest.title.should == "A more advanced test"
|
23
|
+
SimpleTest.description.should == "It does really nice stuff"
|
24
|
+
ExtraTest.description.should == "It does even nicer stuff"
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geoffrey
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Albert Llop
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-08-28 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bundler
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
- rc
|
33
|
+
- 5
|
34
|
+
version: 1.0.0.rc.5
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 3
|
48
|
+
- 0
|
49
|
+
version: 1.3.0
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: mocha
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
segments:
|
61
|
+
- 0
|
62
|
+
- 9
|
63
|
+
- 8
|
64
|
+
version: 0.9.8
|
65
|
+
type: :development
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: plist4r
|
69
|
+
prerelease: false
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
type: :runtime
|
79
|
+
version_requirements: *id004
|
80
|
+
description: "geoffrey\n\
|
81
|
+
========\n\n\
|
82
|
+
## ALERT!\n\n\
|
83
|
+
This is very early alpha code, use with precaution. It's a spinoff of myself willing to\n\
|
84
|
+
improve my [dotfiles project](http://github.com/albertllop/dotfiles) a step further. All\n\
|
85
|
+
code examples in this README come from it.\n\n\
|
86
|
+
## Introduction\n\n\
|
87
|
+
Geoffrey's your little helper, that who just wants to makes your life easier.\n\n\
|
88
|
+
It aims to help you create little scripts to setup your OSX the way you like.\n\
|
89
|
+
If, like me, you use different computers at work, home, or even when travelling,\n\
|
90
|
+
you'll know it's a pain in the ass to keep everything up to date.\n\n\
|
91
|
+
Inspired in the numerous dotfiles projects, specially\n\
|
92
|
+
[holman's](http://github.com/holman/dotfiles),\n\
|
93
|
+
the intention is to bring customization to a bigger extend.\n\n\
|
94
|
+
## Installation\n\n $ [sudo] gem install geoffrey\n\n\
|
95
|
+
Geoffrey's Talents\n\
|
96
|
+
==================\n\n\
|
97
|
+
Geoffrey has many talents, and thus you'll find he can help you in one of these areas:\n\n\
|
98
|
+
## Packages\n\n\
|
99
|
+
If you ever used [Ciar\xC3\xA1n Walsh's](http://ciaranwal.sh) SIMBL plugins, you'll remember\n\
|
100
|
+
what a pain it is to install them every time. Now you can do so with the next piece of code:\n\n require 'geoffrey'\n Geoffrey.package do\n url 'http://www.culater.net/dl/files/SIMBL-0.9.7a.zip'\n options :sudo => true, :unless => Proc.new{ File.exists?(\"/Library/LaunchAgents/net.culater.SIMBL.Agent.plist\") }\n end\n\n\
|
101
|
+
Geoffrey will take care of downloading the zip file, and install whatever .pkg\n\
|
102
|
+
file is in the zip. The possible options are:\n\n\
|
103
|
+
* `:sudo` => in case it needs to be executed as sudo to install (it does if the installer would ever ask for your password)\n\
|
104
|
+
* `:unless` => in order to make running this idempotent.\n\
|
105
|
+
* `:file` => specify which of the files contained in the zip has to be installed. If it's not specified it uses the first .pkg it finds.\n\n\
|
106
|
+
With that you'll have SIMBL installed and working. Now suppose you want to install a bundle.\n\
|
107
|
+
You'd have to download a file, and move it to a directory. Geoffrey can help you a little,\n\
|
108
|
+
basically downloading and uncompressing the zip, and you just have to define the install\n\
|
109
|
+
method.\n\n require 'geoffrey'\n Geoffrey.package do\n url \"http://github.com/dabeeeenster/terminaltabswitching/raw/master/TerminalTabSwitching.bundle.zip\"\n options :file => \"TerminalTabSwitching.bundle\"\n\n def install\n plugins_dir = \"#{ENV[\"HOME\"]}/Library/Application Support/SIMBL/Plugins\"\n FileUtils.mkdir_p plugins_dir\n FileUtils.mv file_to_install, plugins_dir, :force => true\n end\n\n end\n\n\
|
110
|
+
`file_to_install` is provided by geoffrey poiting to the automatically downloaded/uncompressed file.\n\n\
|
111
|
+
## Application Configuration\n\n\
|
112
|
+
Everything in OSX seems to work around `.plist` files. This takes a little bit of work to figure out,\n\
|
113
|
+
but once you do, you can have your favourite apps the way you like. This is my script to get Terminal.app\n\
|
114
|
+
up and running with Pro scheme, Menlo Font 14pt, and a size 520x100.\n\n require 'geoffrey'\n\n Geoffrey.plist do\n file :terminal\n affects \"/Applications/Utilities/Terminal.app\"\n\n options[\"Default Window Settings\"] = \"Pro\"\n options[\"Startup Window Settings\"] = \"Pro\"\n options[\"HasMigratedDefaults\"] = true\n options[\"Window Settings\"][\"Pro\"][\"Font\"] = \"bplist00\\xD4\\x01\\x02\\x03\\x04\\x05\\x06\\x18\\x19X$versionX$objectsY$archiverT$top\\x12\\x00\\x01\\x86\\xA0\\xA4\\a\\b\\x11\\x12U$null\\xD4\\t\\n\\v\\f\\r\\x0E\\x0F\\x10V$classVNSNameVNSSizeXNSfFlags\\x80\\x03\\x80\\x02\\#@,\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x10]Menlo-Regular\\xD2\\x13\\x14\\x15\\x16Z$classnameX$classesVNSFont\\xA2\\x15\\x17XNSObject_\\x10\\x0FNSKeyedArchiver\\xD1\\x1A\\eTroot\\x80\\x01\\b\\x11\\x1A#-27<BKRY`ikmvx\\x86\\x8B\\x96\\x9F\\xA6\\xA9\\xB2\\xC4\\xC7\\xCC\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x1C\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xCE\"\n options[\"Window Settings\"][\"Pro\"][\"Font\"].blob = true\n options[\"Window Settings\"][\"Pro\"][\"columnCount\"] = 520\n options[\"Window Settings\"][\"Pro\"][\"rowCount\"] = 100\n end\n\n\
|
115
|
+
* `file` => Geoffrey knows of a few files in your system you can specify with symbols. If you want to work with a different one, just write the full path.\n\
|
116
|
+
* `affects` => When you close Terminal.app, it'll dump its otions into the plist. So you have to stop it, change the plist file, then reopen it. Geoffrey does this automatically if you tell him what must be rebooted.\n\
|
117
|
+
* `options` => Its the plist has per se. Using the fantastic [plist4r](http://github.com/dreamcat4/plist4r) gem, you can modify it.\n\n\
|
118
|
+
You might have seen something peculiar:\n\n options[\"Window Settings\"][\"Pro\"][\"Font\"].blob = true\n\n\
|
119
|
+
Some values in plist files are of type \"Data\", which is just binary stuff. Plist4r handles\n\
|
120
|
+
these as strings with a special flag.\n\n\
|
121
|
+
The best way to know what to put in every value, is to just go to the file and take a\n\
|
122
|
+
look. They all tend to make sense. For data values, however, you might have more work. The\n\
|
123
|
+
way I do it is opening the file with Plist4r, and reading the value:\n\n require 'plist4r'\n plist = Plist4r.open(\"the/file.plist\")\n plist[\"whatever\"][\"option\"] # => copy whatever it returns\n\n\
|
124
|
+
Just make sure that when you set it in your geoffrey you put the flag blog true. Otherwise you might see some really weird system errors.\n\n\
|
125
|
+
## A few words\n\n\
|
126
|
+
This is work done in my free hours, it's not yet finished. The code is dirty and mainly undocumented. It all started on #whyday,\n\
|
127
|
+
but I'm so lazy that I've needed a lot of time to do just this. \n\n\
|
128
|
+
Thanks!\n"
|
129
|
+
email:
|
130
|
+
- mrsimo@gmail.com
|
131
|
+
executables: []
|
132
|
+
|
133
|
+
extensions: []
|
134
|
+
|
135
|
+
extra_rdoc_files: []
|
136
|
+
|
137
|
+
files:
|
138
|
+
- .gitignore
|
139
|
+
- Gemfile
|
140
|
+
- Gemfile.lock
|
141
|
+
- README.md
|
142
|
+
- Rakefile
|
143
|
+
- geoffrey.gemspec
|
144
|
+
- lib/geoffrey.rb
|
145
|
+
- lib/geoffrey/package.rb
|
146
|
+
- lib/geoffrey/plist.rb
|
147
|
+
- lib/geoffrey/template.rb
|
148
|
+
- lib/geoffrey/version.rb
|
149
|
+
- spec/package_spec.rb
|
150
|
+
- spec/plist_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
- spec/static/example.plist
|
153
|
+
- spec/static/test.tar.gz
|
154
|
+
- spec/static/test.tgz
|
155
|
+
- spec/static/test.txt.gz
|
156
|
+
- spec/static/test.txt.zip
|
157
|
+
- spec/template_spec.rb
|
158
|
+
has_rdoc: true
|
159
|
+
homepage:
|
160
|
+
licenses: []
|
161
|
+
|
162
|
+
post_install_message:
|
163
|
+
rdoc_options: []
|
164
|
+
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
segments:
|
173
|
+
- 0
|
174
|
+
version: "0"
|
175
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
176
|
+
none: false
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
segments:
|
181
|
+
- 1
|
182
|
+
- 3
|
183
|
+
- 6
|
184
|
+
version: 1.3.6
|
185
|
+
requirements: []
|
186
|
+
|
187
|
+
rubyforge_project: geoffrey
|
188
|
+
rubygems_version: 1.3.7
|
189
|
+
signing_key:
|
190
|
+
specification_version: 3
|
191
|
+
summary: Geoffrey is a little helper to aid in the installation of packages and configuration of various Mac OSX applications.
|
192
|
+
test_files: []
|
193
|
+
|