sxp 0.0.14 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/AUTHORS CHANGED
@@ -1 +1 @@
1
- * Arto Bendiken <arto.bendiken@gmail.com>
1
+ * Arto Bendiken <arto@bendiken.net>
data/README CHANGED
@@ -1,21 +1,18 @@
1
- SXP.rb: S-Expressions for Ruby
2
- ==============================
1
+ #SXP.rb: S-Expressions for Ruby
3
2
 
4
3
  This is a Ruby implementation of a universal [S-expression][] parser.
5
4
 
6
5
  * <http://sxp.rubyforge.org/>
7
6
  * <http://github.com/bendiken/sxp-ruby>
8
7
 
9
- Features
10
- --------
8
+ ##Features
11
9
 
12
10
  * Parses S-expressions in universal, [Scheme][], [Common Lisp][], or
13
11
  [SPARQL][] syntax.
14
12
  * Adds a `#to_sxp` method to Ruby objects.
15
13
  * Compatible with Ruby 1.8.7+, Ruby 1.9.x, and JRuby 1.4/1.5.
16
14
 
17
- Examples
18
- --------
15
+ ##Examples
19
16
 
20
17
  require 'sxp'
21
18
 
@@ -49,8 +46,11 @@ Examples
49
46
 
50
47
  SXP::Reader::SPARQL.read %q((base <http://ar.to/>)) #=> [:base, RDF::URI('http://ar.to/')]
51
48
 
52
- Documentation
53
- -------------
49
+ ### Writing an SXP with formatting
50
+
51
+ SXP::Generator.print([:and, true, false]) #=> (and #t #f)
52
+
53
+ ##Documentation
54
54
 
55
55
  * <http://sxp.rubyforge.org/>
56
56
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.14
1
+ 0.1.0
data/lib/sxp.rb CHANGED
@@ -39,8 +39,13 @@ module SXP
39
39
  ##
40
40
  # Reads all S-expressions from the given input files.
41
41
  #
42
- # @param [Enumerable<String>] filenames
43
- # @param [Hash{Symbol => Object}] options
42
+ # @overload read_files(*filenames)
43
+ # @param [Enumerable<String>] filenames
44
+ #
45
+ # @overload read_files(*filenames, options)
46
+ # @param [Enumerable<String>] filenames
47
+ # @param [Hash{Symbol => Object}] options
48
+ #
44
49
  # @return [Enumerable<Object>]
45
50
  def self.read_files(*filenames)
46
51
  Reader::Scheme.read_files(*filenames)
@@ -75,6 +80,15 @@ module SXP
75
80
  def self.read(input, options = {})
76
81
  Reader::Scheme.read(input, options)
77
82
  end
83
+
84
+ ##
85
+ # Write an internal S-Expression as a formatted SXP
86
+ #
87
+ # @param[Array<Object>] sxp
88
+ # @param[#write] output
89
+ def self.write(sxp, output = STDOUT)
90
+ Generator.write(output, sxp)
91
+ end
78
92
 
79
93
  class << self
80
94
  alias_method :parse, :read
data/lib/sxp/generator.rb CHANGED
@@ -1,16 +1,102 @@
1
1
  module SXP
2
2
  ##
3
3
  # An S-expression generator.
4
+ #
5
+ # Takes an object and pretty-prints it using reasonable indentation rules
4
6
  class Generator
5
7
  ##
8
+ # A basic block containing constituent
9
+ # objects, either blocks or strings.
10
+ class Block
11
+ BLOCK_MIN_LENGTH = 40
12
+
13
+ # @attr [Integer] amount of indent applied to this block
14
+ attr_reader :indent
15
+
16
+ ##
17
+ # @param [Object] obj
18
+ def initialize(obj, indent)
19
+ @indent = indent
20
+ @elements = []
21
+ if obj.is_a?(Array)
22
+ obj.compact.each {|o| @elements << Block.new(o, indent + 1)}
23
+ else
24
+ @elements = obj
25
+ end
26
+ end
27
+
28
+ ##
29
+ # Agregate length over each element accounting for spaces
30
+ #
31
+ # @return [Integer]
32
+ # If indent is not not nil, returns zero
33
+ def length
34
+ if @elements.is_a?(Array)
35
+ @elements.map(&:length).inject(:+).to_i + @elements.length - 1
36
+ else
37
+ @elements.to_sxp.length
38
+ end
39
+ end
40
+
41
+ ##
42
+ # Turn block into a string in S-expression form
43
+ # This should only be called on a block when
44
+ # no indentation is to be applied
45
+ # @return [String]
46
+ def to_sxp
47
+ @elements.to_sxp
48
+ end
49
+
50
+ ##
51
+ # Determins if this block is an SXP, or not
52
+ # @return [Boolean]
53
+ def sxp?
54
+ @elements.is_a?(Array)
55
+ end
56
+
57
+ ##
58
+ # Output block applying indent recursively
59
+ # @param [#write] io
60
+ def write(io)
61
+ # Output individual block elements on separate lines
62
+ if sxp? && length > BLOCK_MIN_LENGTH
63
+ io.write(do_indent + '(')
64
+ first, *elems = @elements
65
+ unless first.sxp?
66
+ # It's atomic, write out after paren
67
+ io.puts(first.to_sxp)
68
+ else
69
+ io.write("\n")
70
+ elems.unshift(first)
71
+ end
72
+ elems.each do |e|
73
+ e.write(io)
74
+ end
75
+ io.puts(do_indent + ")\n")
76
+ else
77
+ io.puts(do_indent + @elements.to_sxp)
78
+ end
79
+ end
80
+
81
+ private
82
+ def do_indent(offset = 0); ' ' * (indent + offset); end
83
+ end
84
+
85
+ ##
86
+ # Format S-expressions to a String
87
+ #
6
88
  # @param [Array] sxps
7
89
  # @return [Object]
8
90
  def self.string(*sxps)
9
91
  require 'stringio' unless defined?(StringIO)
10
- write(StringIO.new, *sxps).instance_variable_get('@buffer').string
92
+ buf = StringIO.new
93
+ write(buf, *sxps)
94
+ buf.string
11
95
  end
12
96
 
13
97
  ##
98
+ # Format S-expressions to STDOUT
99
+ #
14
100
  # @param [Array] sxps
15
101
  # @return [Object]
16
102
  def self.print(*sxps)
@@ -18,73 +104,46 @@ module SXP
18
104
  end
19
105
 
20
106
  ##
107
+ # Write formatted S-expressions to an IO like object
108
+ #
21
109
  # @param [Object] out
22
110
  # @param [Array] sxps
23
111
  # @return [Object]
24
112
  def self.write(out, *sxps)
25
113
  generator = self.new(out)
26
114
  sxps.each do |sxp|
27
- generator.send((op = sxp.shift).to_sym, *sxp)
115
+ generator.render(sxp)
28
116
  end
29
117
  generator
30
118
  end
31
119
 
32
120
  ##
33
- # @param [Object] buffer
121
+ # Initialize output with a stack of IO buffers
122
+ #
123
+ # @param [#write] buffer
34
124
  def initialize(buffer)
35
- @output = [@buffer = buffer]
36
- @indent = 0
37
- end
38
-
39
- protected
40
-
41
- ##
42
- # @param [String] text
43
- # @param [Hash{Symbol => Object}] options
44
- # @return [void]
45
- def emit(text, options = {})
46
- if out = @output.last
47
- out.print(' ' * (indent * 2)) if options[:indent]
48
- out.print(text)
49
- end
50
- end
51
-
52
- ##
53
- # @yield
54
- # @return [String]
55
- def captured(&block)
56
- require 'stringio' unless defined?(StringIO)
57
- begin
58
- @output.push(buffer = StringIO.new)
59
- block.call
60
- ensure
61
- @output.pop
62
- end
63
- buffer.string
125
+ @output = buffer
64
126
  end
65
127
 
66
128
  ##
67
- # @yield
68
- # @return [Object]
69
- def indented(&block)
70
- begin
71
- increase_indent!
72
- block.call
73
- ensure
74
- decrease_indent!
129
+ # Render an element.
130
+ # For Array, this recursively renders each constituent into blocks.
131
+ # If the agregate length of a block is less than MIN_BLOCK characters,
132
+ # combine each constituent block into a single line.
133
+ #
134
+ # Rendering does not perform final formatting, but returns a recursive
135
+ # array of blocks which are each ultimattely formattted onto their
136
+ # own line with leading whitespace.
137
+ #
138
+ # @param [Object] sexp
139
+ # @return [Block]
140
+ def render(sexp)
141
+ block = Block.new(sexp, 0)
142
+ if block.length > 40
143
+ block.write(@output)
144
+ else
145
+ @output.puts(block.to_sxp)
75
146
  end
76
147
  end
77
-
78
- ##
79
- # @return [void]
80
- def increase_indent!
81
- @indent += 1
82
- end
83
-
84
- ##
85
- # @return [void]
86
- def decrease_indent!
87
- @indent -= 1
88
- end
89
148
  end # Generator
90
149
  end # SXP
data/lib/sxp/reader.rb CHANGED
@@ -22,16 +22,21 @@ module SXP
22
22
  # @return [Enumerable<Object>]
23
23
  def self.read_url(url, options = {})
24
24
  require 'open-uri'
25
- open(url.to_s, 'rb', nil, options) { |io| read_all(io, options) }
25
+ open(url.to_s, 'rb', nil, options) { |io| read_all(io, options).first }
26
26
  end
27
27
 
28
28
  ##
29
29
  # Reads all S-expressions from the given input files.
30
30
  #
31
- # @param [Enumerable<String>] filenames
32
- # @param [Hash{Symbol => Object}] options
31
+ # @overload read_files(*filenames)
32
+ # @param [Enumerable<String>] filenames
33
+ #
34
+ # @overload read_files(*filenames, options)
35
+ # @param [Enumerable<String>] filenames
36
+ # @param [Hash{Symbol => Object}] options
37
+ #
33
38
  # @return [Enumerable<Object>]
34
- def self.read_files(*filenames)
39
+ def read_files(*filenames)
35
40
  options = filenames.last.is_a?(Hash) ? filenames.pop : {}
36
41
  filenames.map { |filename| read_file(filename, options) }.inject { |sxps, sxp| sxps + sxp }
37
42
  end
@@ -43,7 +48,7 @@ module SXP
43
48
  # @param [Hash{Symbol => Object}] options
44
49
  # @return [Enumerable<Object>]
45
50
  def self.read_file(filename, options = {})
46
- File.open(filename.to_s, 'rb') { |io| read_all(io, options) }
51
+ File.open(filename.to_s, 'rb') { |io| read_all(io, options).first }
47
52
  end
48
53
 
49
54
  ##
@@ -55,13 +55,8 @@ module SXP; class Reader
55
55
  # @example Returning a URI prefix
56
56
  # parser.prefix(:dc) #=> RDF::URI('http://purl.org/dc/terms/')
57
57
  #
58
- # @overload prefix(name, uri)
59
- # @param [Symbol, #to_s] name
60
- # @param [RDF::URI, #to_s] uri
61
- #
62
- # @overload prefix(name)
63
- # @param [Symbol, #to_s] name
64
- #
58
+ # @param [Symbol, #to_s] name
59
+ # @param [RDF::URI, #to_s] uri
65
60
  # @return [RDF::URI]
66
61
  def prefix(name, uri = nil)
67
62
  name = name.to_s.empty? ? nil : (name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym)
data/lib/sxp/version.rb CHANGED
@@ -1,9 +1,7 @@
1
1
  module SXP
2
2
  module VERSION
3
- MAJOR = 0
4
- MINOR = 0
5
- TINY = 14
6
- EXTRA = nil
3
+ VERSION_FILE = File.expand_path("../../../VERSION", __FILE__)
4
+ MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chop.split(".")
7
5
 
8
6
  STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
9
7
 
metadata CHANGED
@@ -1,79 +1,74 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: sxp
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 14
9
- version: 0.0.14
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Arto Bendiken
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-04-04 00:00:00 +02:00
18
- default_executable: sxp2rdf
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-11-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: json
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 5
31
- - 1
32
- version: 1.5.1
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.4.6
33
22
  type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: yard
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
39
25
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- segments:
44
- - 0
45
- - 6
46
- - 4
47
- version: 0.6.4
48
- type: :development
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.4.6
30
+ - !ruby/object:Gem::Dependency
51
31
  name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 2.12.0
38
+ type: :development
52
39
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
54
41
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- segments:
59
- - 2
60
- - 5
61
- - 0
62
- version: 2.5.0
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.12.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: yard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.8.3
63
54
  type: :development
64
- version_requirements: *id003
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.3
65
62
  description: A pure-Ruby implementation of a universal S-expression parser.
66
- email: arto.bendiken@gmail.com
67
- executables:
63
+ email: arto@bendiken.net
64
+ executables:
68
65
  - sxp2rdf
69
66
  - sxp2json
70
67
  - sxp2xml
71
68
  - sxp2yaml
72
69
  extensions: []
73
-
74
70
  extra_rdoc_files: []
75
-
76
- files:
71
+ files:
77
72
  - AUTHORS
78
73
  - CREDITS
79
74
  - README
@@ -96,39 +91,30 @@ files:
96
91
  - bin/sxp2json
97
92
  - bin/sxp2xml
98
93
  - bin/sxp2yaml
99
- has_rdoc: false
100
94
  homepage: http://sxp.rubyforge.org/
101
- licenses:
95
+ licenses:
102
96
  - Public Domain
103
97
  post_install_message:
104
98
  rdoc_options: []
105
-
106
- require_paths:
99
+ require_paths:
107
100
  - lib
108
- required_ruby_version: !ruby/object:Gem::Requirement
101
+ required_ruby_version: !ruby/object:Gem::Requirement
109
102
  none: false
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- segments:
114
- - 1
115
- - 8
116
- - 1
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
117
106
  version: 1.8.1
118
- required_rubygems_version: !ruby/object:Gem::Requirement
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
108
  none: false
120
- requirements:
121
- - - ">="
122
- - !ruby/object:Gem::Version
123
- segments:
124
- - 0
125
- version: "0"
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
126
113
  requirements: []
127
-
128
114
  rubyforge_project: sxp
129
- rubygems_version: 1.3.7
115
+ rubygems_version: 1.8.24
130
116
  signing_key:
131
117
  specification_version: 3
132
118
  summary: A pure-Ruby implementation of a universal S-expression parser.
133
119
  test_files: []
134
-
120
+ has_rdoc: false