graffle 0.1.0
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.
- data/History.txt +2 -0
- data/LICENSE.txt +34 -0
- data/Manifest.txt +53 -0
- data/README.txt +19 -0
- data/Rakefile +32 -0
- data/Rakefile.hoe +23 -0
- data/bin/bin-skeleton +23 -0
- data/graffle.tmproj +335 -0
- data/lib/graffle.rb +43 -0
- data/lib/graffle/.document +4 -0
- data/lib/graffle/lib-skeleton +3 -0
- data/lib/graffle/nodoc/hacks.rb +69 -0
- data/lib/graffle/point.rb +42 -0
- data/lib/graffle/stereotypes.rb +446 -0
- data/lib/graffle/styled-text-reader.rb +52 -0
- data/lib/graffle/third-party/s4t-utils.rb +21 -0
- data/lib/graffle/third-party/s4t-utils/capturing-globals.rb +78 -0
- data/lib/graffle/third-party/s4t-utils/claims.rb +14 -0
- data/lib/graffle/third-party/s4t-utils/command-line.rb +15 -0
- data/lib/graffle/third-party/s4t-utils/error-handling.rb +20 -0
- data/lib/graffle/third-party/s4t-utils/friendly-format.rb +27 -0
- data/lib/graffle/third-party/s4t-utils/hacks.rb +32 -0
- data/lib/graffle/third-party/s4t-utils/load-path-auto-adjuster.rb +120 -0
- data/lib/graffle/third-party/s4t-utils/more-assertions.rb +29 -0
- data/lib/graffle/third-party/s4t-utils/os.rb +28 -0
- data/lib/graffle/third-party/s4t-utils/rake-task-helpers.rb +75 -0
- data/lib/graffle/third-party/s4t-utils/rakefile-common.rb +106 -0
- data/lib/graffle/third-party/s4t-utils/svn-file-movement.rb +101 -0
- data/lib/graffle/third-party/s4t-utils/test-util.rb +19 -0
- data/lib/graffle/third-party/s4t-utils/version.rb +3 -0
- data/lib/graffle/version.rb +8 -0
- data/setup.rb +1585 -0
- data/test/abstract-graphic-tests.rb +56 -0
- data/test/array-and-hash-stereotyping-tests.rb +49 -0
- data/test/document-tests.rb +117 -0
- data/test/graffle-file-types/as-a-package.graffle/data.plist +953 -0
- data/test/graffle-file-types/as-a-package.graffle/image1.png +0 -0
- data/test/graffle-file-types/as-a-package.graffle/image2.png +0 -0
- data/test/graffle-file-types/as-a-package.graffle/image3.png +0 -0
- data/test/graffle-file-types/multiple-canvases.graffle +6821 -0
- data/test/graffle-file-types/opening-tests.rb +45 -0
- data/test/graffle-file-types/two-boxes-and-a-line.graffle +347 -0
- data/test/group-tests.rb +109 -0
- data/test/hacks-tests.rb +58 -0
- data/test/line-graphic-tests.rb +155 -0
- data/test/point-tests.rb +43 -0
- data/test/set-standalone-test-paths.rb +5 -0
- data/test/shaped-graphic-tests.rb +93 -0
- data/test/sheet-tests.rb +124 -0
- data/test/styled-text-reader-tests.rb +89 -0
- data/test/test-skeleton +19 -0
- data/test/text-tests.rb +55 -0
- data/test/util.rb +15 -0
- metadata +139 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Created by Brian Marick on 2007-07-06.
|
4
|
+
# Copyright (c) 2007. All rights reserved.
|
5
|
+
|
6
|
+
|
7
|
+
module Graffle
|
8
|
+
|
9
|
+
class StyledTextReader # :nodoc:
|
10
|
+
attr_reader :raw_text
|
11
|
+
|
12
|
+
def initialize(string)
|
13
|
+
@raw_text = string
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_rtf?
|
17
|
+
@raw_text.starts_with?("{\\rtf")
|
18
|
+
end
|
19
|
+
|
20
|
+
def without_rtf_header
|
21
|
+
lines = @raw_text.split("\n")
|
22
|
+
return lines unless self.is_rtf?
|
23
|
+
|
24
|
+
lines.each_with_index do | elt, index |
|
25
|
+
unless elt.starts_with?("\\") or elt.starts_with?("{")
|
26
|
+
index += 1 # skip past blank line
|
27
|
+
return lines[index..-1]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def as_lines
|
33
|
+
lines = without_rtf_header
|
34
|
+
return lines unless self.is_rtf?
|
35
|
+
|
36
|
+
lines = lines.reject { |line| line.starts_with?("\\par") }
|
37
|
+
lines.collect do |line|
|
38
|
+
line = line.gsub(/^\\f\d\\fs\d\d \\cf\d /, '')
|
39
|
+
line = line.gsub(/\}$/, '')
|
40
|
+
line = line.gsub(/\\$/, '')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def as_tokens_within_lines
|
45
|
+
self.as_lines.collect do |line|
|
46
|
+
line.split(/",?/).collect { |tok| tok.strip }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 's4t-utils/capturing-globals'
|
2
|
+
require 's4t-utils/error-handling'
|
3
|
+
require 's4t-utils/more-assertions'
|
4
|
+
require 's4t-utils/claims'
|
5
|
+
require 's4t-utils/friendly-format'
|
6
|
+
require 's4t-utils/rake-task-helpers'
|
7
|
+
require 's4t-utils/svn-file-movement'
|
8
|
+
require 's4t-utils/hacks'
|
9
|
+
require 's4t-utils/command-line'
|
10
|
+
require 's4t-utils/test-util'
|
11
|
+
require 's4t-utils/os'
|
12
|
+
|
13
|
+
require 'pp'
|
14
|
+
|
15
|
+
# Tolerate typos
|
16
|
+
S4TUtils=S4tUtils
|
17
|
+
S4tUtil=S4tUtils
|
18
|
+
S4TUtil=S4tUtils
|
19
|
+
|
20
|
+
module S4tUtils
|
21
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module S4tUtils
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def capturing_stderr
|
8
|
+
old_stderr = $stderr
|
9
|
+
new_stderr = StringIO.new
|
10
|
+
begin
|
11
|
+
$stderr = new_stderr
|
12
|
+
yield
|
13
|
+
ensure
|
14
|
+
$stderr = old_stderr
|
15
|
+
end
|
16
|
+
new_stderr.string
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_environment_vars(settings)
|
20
|
+
begin
|
21
|
+
old = {}
|
22
|
+
settings.each { | key, value |
|
23
|
+
old[key] = ENV[key]
|
24
|
+
ENV[key] = value
|
25
|
+
}
|
26
|
+
yield
|
27
|
+
ensure
|
28
|
+
settings.each_key { | key |
|
29
|
+
ENV[key] = old[key]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def with_home_right_here
|
35
|
+
begin
|
36
|
+
old_home = ENV['HOME']
|
37
|
+
ENV['HOME'] = '.'
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
ENV['HOME'] = @old_home
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def erasing_local_config_file(file)
|
45
|
+
with_home_right_here {
|
46
|
+
begin
|
47
|
+
File.delete(file) if File.exist?(file)
|
48
|
+
yield
|
49
|
+
ensure
|
50
|
+
File.delete(file) if File.exist?(file)
|
51
|
+
end
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def with_local_config_file(file, contents)
|
56
|
+
erasing_local_config_file(file) do
|
57
|
+
File.open(file, 'w') do | io |
|
58
|
+
io.puts(contents.to_s)
|
59
|
+
end
|
60
|
+
yield
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def with_command_args(string)
|
65
|
+
begin
|
66
|
+
old_argv = ARGV.dup
|
67
|
+
ARGV.replace(string.split)
|
68
|
+
yield
|
69
|
+
rescue SystemExit => ex
|
70
|
+
replacement = StandardError.new(ex.message)
|
71
|
+
replacement.set_backtrace(ex.backtrace)
|
72
|
+
raise replacement
|
73
|
+
ensure
|
74
|
+
ARGV.replace(old_argv)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module S4tUtils
|
2
|
+
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def with_pleasant_exceptions
|
6
|
+
yield
|
7
|
+
rescue SystemExit
|
8
|
+
raise
|
9
|
+
rescue Exception => ex
|
10
|
+
$stderr.puts(ex.message)
|
11
|
+
end
|
12
|
+
|
13
|
+
# with_pleasant_exceptions swallows the stack trace, which you
|
14
|
+
# want to see during debugging. The easy way to see it is to add
|
15
|
+
# 'out' to the method, giving this:
|
16
|
+
def without_pleasant_exceptions
|
17
|
+
$stderr.puts "Note: exception handling turned off."
|
18
|
+
yield
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Note: see also <http://englishext.rubyforge.org/>
|
2
|
+
|
3
|
+
module S4tUtils
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def friendly_list(connector, array)
|
8
|
+
quoted = array.collect { | elt | "'" + elt.to_s + "'" }
|
9
|
+
case array.length
|
10
|
+
when 0
|
11
|
+
""
|
12
|
+
when 1
|
13
|
+
quoted[0]
|
14
|
+
when 2
|
15
|
+
quoted[0] + " #{connector} " + quoted[1]
|
16
|
+
else
|
17
|
+
quoted[0...-1].join(", ") + ", #{connector} #{quoted.last}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Produces a version of a string that can be typed after a :
|
22
|
+
# (Can also be safely given at a command-line prompt.
|
23
|
+
def symbol_safe_name(name)
|
24
|
+
name.to_s.gsub(/\W/, '')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module S4tUtils
|
2
|
+
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def prog1(retval)
|
6
|
+
yield(retval)
|
7
|
+
retval
|
8
|
+
end
|
9
|
+
|
10
|
+
# Allow debugging like this:
|
11
|
+
# x = pi y # adding pi doesn't change effect of x=y
|
12
|
+
def pi(arg, leader=nil)
|
13
|
+
leader = (leader == nil) ? '' : leader + ': '
|
14
|
+
prog1(arg) { puts leader + arg.inspect }
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class ArgForwarder
|
20
|
+
def initialize(target, *added_args)
|
21
|
+
@target = target
|
22
|
+
@added_args = added_args
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args)
|
26
|
+
@target.send(method, *(@added_args + args))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# This is loaded by an executable script in one of two cases:
|
2
|
+
#
|
3
|
+
# It's a development version living in the bin part of this directory
|
4
|
+
# structure (but it can invoked from any place).
|
5
|
+
#
|
6
|
+
# project/
|
7
|
+
# bin/
|
8
|
+
# lib/
|
9
|
+
# project/
|
10
|
+
# third-party/
|
11
|
+
# s4t-utils/
|
12
|
+
# this file
|
13
|
+
#
|
14
|
+
# It's a deployed version living in some random place, with
|
15
|
+
# the site_ruby directory in the page.
|
16
|
+
#
|
17
|
+
# site_ruby/1.8/
|
18
|
+
# project/
|
19
|
+
# third-party/
|
20
|
+
# s4t-utils/
|
21
|
+
# this file
|
22
|
+
#
|
23
|
+
#
|
24
|
+
# In order for this file to have been required in both cases, the following
|
25
|
+
# code is executed in the caller:
|
26
|
+
#
|
27
|
+
#
|
28
|
+
# $:.unshift((Pathname.new(__FILE__).parent.parent + 'lib').to_s)
|
29
|
+
# require 'package/third-party/s4t-utils/load-path-auto-adjuster'
|
30
|
+
#
|
31
|
+
# In the first case, that will put something like "../lib" on the load
|
32
|
+
# path. In the second case, it will put harmless garbage on the path
|
33
|
+
# (harmless because it won't contain this file, which will still be
|
34
|
+
# found somewhere later in the load path).
|
35
|
+
#
|
36
|
+
# The first thing this file does is pop that off, it having done its job.
|
37
|
+
# In the first (development) case, it puts the following on the load path:
|
38
|
+
# project/lib & project/lib/project/third-party & project
|
39
|
+
# ('project' is added so that <require 'test/util-file'> works.)
|
40
|
+
#
|
41
|
+
# In the second, it adds only the third-party library and takes care
|
42
|
+
# to add it just after whatever component in the path contains this
|
43
|
+
# file. (It will thus not interfere with clashing packages earlier
|
44
|
+
# in the path.)
|
45
|
+
# site_ruby/1.8/project/third-party
|
46
|
+
# since site_ruby/1.8 (or the equivalent) is already on there.
|
47
|
+
|
48
|
+
require 'rubygems'
|
49
|
+
require 'pathname'
|
50
|
+
|
51
|
+
module S4tUtils
|
52
|
+
module Hidden # This should not interfere with any namespace.
|
53
|
+
|
54
|
+
class Arranger
|
55
|
+
def initialize(third_party)
|
56
|
+
@third_party_lib = third_party
|
57
|
+
@project_lib = third_party.parent.parent
|
58
|
+
@test_util_root = @project_lib.parent
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.arrange_path_around(third_party)
|
62
|
+
new(third_party).arrange
|
63
|
+
end
|
64
|
+
|
65
|
+
def arrange
|
66
|
+
add_third_party_gems
|
67
|
+
if project_lib_already_in_path?
|
68
|
+
just_add_third_party_after_project_lib
|
69
|
+
else
|
70
|
+
add_everything_at_front
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def add_third_party_gems
|
76
|
+
# When RubyGems 0.8.11 gets clear_paths, it does not clear the
|
77
|
+
# cache used by Gem's overriding version of require(), so if
|
78
|
+
# this is loaded after the first Gem is required, it will have
|
79
|
+
# no effect on later uses of require(). (But it does affect
|
80
|
+
# require_gem.)
|
81
|
+
#
|
82
|
+
ENV['GEM_PATH']=(@third_party_lib+'gems').to_s
|
83
|
+
Gem.clear_paths
|
84
|
+
end
|
85
|
+
|
86
|
+
def project_lib_already_in_path?
|
87
|
+
$:.include?(@project_lib.to_s)
|
88
|
+
end
|
89
|
+
|
90
|
+
def just_add_third_party_after_project_lib
|
91
|
+
$:.each_with_index do | path_element, index |
|
92
|
+
if path_element == @project_lib.to_s
|
93
|
+
$:[index+1,0] = @third_party_lib.to_s
|
94
|
+
return
|
95
|
+
end
|
96
|
+
end
|
97
|
+
fail "No place to put third_party library."
|
98
|
+
end
|
99
|
+
|
100
|
+
def add_everything_at_front
|
101
|
+
$:.unshift(@test_util_root.to_s)
|
102
|
+
$:.unshift(@third_party_lib.to_s)
|
103
|
+
$:.unshift(@project_lib.to_s) # This is now first
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.auto_adjust_load_path
|
108
|
+
$:.shift # Remove extra element used to find this file.
|
109
|
+
|
110
|
+
# Having loaded us, __FILE__ is something like this:
|
111
|
+
# ...lib.../package/third-party/s4t-utils/load-path-auto-adjuster.rb
|
112
|
+
relative_third_party = Pathname.new(__FILE__).parent.parent
|
113
|
+
# Pathname#real_path doesn't work on Windows (1.8.2). Grr.
|
114
|
+
third_party = Pathname.new(File.expand_path(relative_third_party.to_s))
|
115
|
+
Arranger.arrange_path_around(third_party)
|
116
|
+
end
|
117
|
+
|
118
|
+
auto_adjust_load_path
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Test
|
2
|
+
module Unit
|
3
|
+
|
4
|
+
module Assertions
|
5
|
+
def assert_true(boolean, message = nil)
|
6
|
+
assert(boolean, message)
|
7
|
+
end
|
8
|
+
|
9
|
+
def assert_false(boolean, message = nil)
|
10
|
+
_wrap_assertion do
|
11
|
+
assert_block(build_message(message, "<?> should be false or nil.", boolean)) { !boolean }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def assert_raise_with_matching_message(exception_class, message, &block)
|
16
|
+
exception = assert_raise(exception_class, &block)
|
17
|
+
assert_match(message, exception.message)
|
18
|
+
end
|
19
|
+
alias_method :assert_raises_with_matching_message,
|
20
|
+
:assert_raise_with_matching_message
|
21
|
+
|
22
|
+
def assert_wants_to_exit
|
23
|
+
assert_raise(SystemExit) do
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module S4tUtils
|
2
|
+
|
3
|
+
def self.on_windows?
|
4
|
+
Config::CONFIG["arch"] =~ /dos|win32/i
|
5
|
+
end
|
6
|
+
|
7
|
+
# Lifted this from Rubygems, which is released under the
|
8
|
+
# Ruby license.
|
9
|
+
def self.find_home # :nodoc:
|
10
|
+
['HOME', 'USERPROFILE'].each do |homekey|
|
11
|
+
return ENV[homekey] if ENV[homekey]
|
12
|
+
end
|
13
|
+
if ENV['HOMEDRIVE'] && ENV['HOMEPATH']
|
14
|
+
return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
|
15
|
+
end
|
16
|
+
begin
|
17
|
+
File.expand_path("~")
|
18
|
+
rescue StandardError => ex
|
19
|
+
if File::ALT_SEPARATOR
|
20
|
+
"C:/"
|
21
|
+
else
|
22
|
+
"/"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
end
|