rbibtex 0.0.1 → 0.0.2

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/CHANGELOG CHANGED
@@ -1,3 +1,12 @@
1
+ 0.0.2
2
+ * Simplified Grammar a bit
3
+ * Now parsing @comment correctly
4
+ * Made rbib2bib actually usefull.
5
+ * Sorting of entries
6
+ * Sorting of fields
7
+ * A help
8
+ * Nicer output respecting formatting.
9
+
1
10
  0.0.1
2
11
  * Removed unneccessary dependency on pp
3
12
  * Added rbib2bib pretty printer
data/InstalledFiles ADDED
@@ -0,0 +1,2 @@
1
+ /home/bschroed//bin/rbib2bib
2
+ /home/bschroed//lib/ruby/site_ruby/1.8/rbibtex/rbibtex.tab.rb
data/README CHANGED
@@ -52,9 +52,13 @@ Brian
52
52
  ## ToDo
53
53
  * The binaries are only quick hacks for my specific applications right now,
54
54
  they should be rewritten and extended.
55
+ * I should transfer functionality from rbib2bib into a library usable by all
56
+ programs.
55
57
  * The full bibtex format is not parsed, I only allow for a specific subset
56
58
  right now.
57
59
  * Escaping is not implemented.
60
+ * Create the documentation after having racc'ed the .y files, then cleanup
61
+ again before packaging.
58
62
 
59
63
  ## Authors
60
64
  This was implemented by Brian Schroeder.
data/bin/rbib2bib CHANGED
@@ -1,76 +1,147 @@
1
- #! /usr/bin/ruby
2
-
3
- $:.unshift("~/lib/ruby")
4
-
5
- require "rbibtex"
6
-
7
- file = BibTeX::Parser.new.parse( ARGF.read )
8
-
9
- first = [:author, :title, :year]
10
- last = [:note, :pdf, :ps, :www]
11
-
12
- puts "@comment { Pretty Printed using rbib2bib }"
13
-
14
- max_key_length = file.inject(0) { | r, entry |
15
- entry.properties.inject(r) { | r, (k, _) |
16
- [r, k.to_s.length].max
17
- }
18
- }
19
-
20
- p max_key_length
1
+ #! /home/bschroed//bin/ruby
21
2
 
3
+ # Some string handling routines for wordwrapping and tabifying.
22
4
  class String
23
5
  def wrap(width = 78, tabwidth = 8)
24
6
  raise "Invalid width" if width < 0
25
7
  self.untabify(tabwidth).
26
- gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n") }.
27
- gsub(/\s*\Z/m, "")
8
+ gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n") }.
9
+ gsub(/\s*\Z/m, "")
28
10
  end
29
11
 
30
12
  def indent_hanging(indent = 2)
31
- self.gsub(/\n/, "\n#{" " * indent}")
13
+ self.gsub(/\n/, "\n#{" " * indent}")
32
14
  end
33
-
15
+
34
16
  def indent(indent = 2)
35
- self.gsub(/^/, " " * indent)
17
+ self.gsub(/^/, " " * indent)
36
18
  end
37
19
 
38
20
 
39
21
  def untabify(tab_width = 8)
40
22
  self.gsub(/\t/, " "*tab_width)
41
23
  end
42
-
24
+
43
25
  def deindent_hanging(indent = [self[/^\s*/].untabify.length, self[/\n(\s*)/, 1].to_s.untabify.length].max)
44
26
  self.untabify.gsub(/^\s{0,#{indent}}/, "")
45
27
  end
46
-
28
+
47
29
  def deindent(indent = self[/^\s*/].untabify.length)
48
30
  self.untabify.gsub(/^\s{0,#{indent}}/, "")
49
31
  end
50
32
 
51
33
  def unwrap
52
34
  self.split(/\n\n+/).map { | paragraph |
53
- paragraph.gsub(/\n(?=\S)/, " ")
35
+ paragraph.gsub(/((?:\n|^)\S[^\n]*)\n(?=\S)/, "\\1 ")
54
36
  }.join("\n\n")
55
37
  end
56
38
  end
57
39
 
58
- file.each do | entry |
59
-
60
- p = entry.properties.dup
61
- f = first.map { | k | [k, p.delete(k)] }
62
- l = last.map { | k | [k, p.delete(k)] }
63
- p = p.to_a.map{ | (k, v) | [k.to_s, v] }.sort
64
-
65
- puts "@#{entry.type}{#{entry.key},"
66
- (f + p + l).each do | (k, v) |
67
- next unless v
68
-
69
- print %( #{k}).ljust(max_key_length+2) + " = {"
70
- print v.deindent_hanging.unwrap.wrap(78-(max_key_length+6)).indent_hanging(max_key_length+6)
71
- puts "},"
40
+ module Bib2Bib
41
+ VERSION = "0.0.2"
42
+
43
+ require 'optparse'
44
+
45
+ class Options < OptionParser
46
+ attr_reader :wrap, :sort_by, :top_fields, :bottom_fields, :output, :help, :show_version, :comment
47
+
48
+ def initialize
49
+ super()
50
+
51
+ # Defaults
52
+ @top_fields = [:author, :title, :year]
53
+ @bottom_fields = [:note, :pdf, :ps, :www]
54
+ @comment = true
55
+ @output = STDOUT
56
+
57
+ # Parser Actions
58
+ self.banner = "Usage: #{ __FILE__ } [-o OUTPUT] [OPTIONS] INPUT [INPUT_1 ...]"
59
+ self.on("-o FILENAME", "--output FILENAME", String,
60
+ "Set the output filename. Writes to stdout if nothing is given") { | v | @output = File.open(v, 'w') }
61
+ self.on("-s", "--sort-by", "--sort_by Field_1,Field2,...", Array,
62
+ "Specify fields that shall be used for sorting of the file") { | v | @sort_by = v.map { | e | e.downcase.to_sym } }
63
+ self.on("-t", "--top_fields Field_1,Field2,...", Array,
64
+ "Specify a list of fields that are written first in the output") { | v | @top_fields = v.map { | e | e.downcase.to_sym }
65
+ @bottom_fields -= @top_fields }
66
+ self.on("-b", "--bottom_fields Field_1,Field2,...", Array,
67
+ "Specify a list of fields that are written last in the output") { | v | @bottom_fields = v.map { | e | e.downcase.to_sym }
68
+ @top_fields -= @bottom_fields }
69
+ self.on("-C", "--no-comment",
70
+ "Suppress generation of 'Created by' comment") { @comment = false }
71
+ self.on("-?", "--help",
72
+ "Show this help") { @help = true }
73
+ self.on("-v", "--version",
74
+ "Output version number and exit") { @show_version = true }
75
+ end
76
+
77
+ def parse!(*args)
78
+ super
79
+ raise "You can't specify an empty list of fields for sorting" if @sort_by and @sort_by.empty?
80
+ end
72
81
  end
73
- puts "}"
74
- puts
75
- end
76
82
 
83
+ options = Options.new
84
+ begin
85
+ options.parse!(ARGV)
86
+ rescue => e
87
+ puts "Invalid Commandline Arguments"
88
+ puts e
89
+ puts options
90
+ exit
91
+ end
92
+
93
+ if options.show_version
94
+ puts VERSION
95
+ exit
96
+ end
97
+
98
+ if options.help
99
+ puts options
100
+ exit
101
+ end
102
+
103
+ require "rbibtex"
104
+
105
+
106
+ entries = BibTeX::Parser.new.parse( ARGF.read )
107
+ O = options.output
108
+
109
+ if @comment
110
+ O.puts "@comment { Pretty Printed using rbib2bib }"
111
+ end
112
+
113
+ # Calculate maximum key length
114
+ max_key_length = entries.entries.inject(0) { | r, entry |
115
+ entry.properties.inject(r) { | r, (k, _) |
116
+ [r, k.to_s.length].max
117
+ }
118
+ }
119
+
120
+ def self.extract_properties(properties, fields)
121
+ fields.map { | k | [k, properties.delete(k)] }.select { | (_, v) | v }
122
+ end
123
+
124
+ elements = entries.elements.select { | e | e.is_a?(BibTeX::Entry) or e.is_a?(BibTeX::Comment) }
125
+ if options.sort_by
126
+ elements = elements.sort_by { | e | e.is_a?(BibTeX::Comment) ? [] : options.sort_by.map { | k | e.properties[k] || "" } }
127
+ end
128
+ puts elements.map { | entry |
129
+
130
+ if entry.is_a?BibTeX::Comment
131
+ "@comment { #{entry.to_s.deindent_hanging.unwrap.wrap(78 - 11).indent_hanging(11)} }"
132
+ else
133
+ properties = entry.properties.dup
134
+ top = extract_properties(properties, options.top_fields)
135
+ bottom = extract_properties(properties, options.bottom_fields)
136
+ middle = properties.to_a.map { | (k, v) | [k.to_s, v] }.sort
137
+
138
+ "@#{entry.type}{#{entry.key},\n" +
139
+ (
140
+ (top + middle + bottom).map { | (k, v) |
141
+ %( #{k}).ljust(max_key_length+2) + " = {#{v.deindent_hanging.unwrap.wrap(78-(max_key_length+6)).indent_hanging(max_key_length+6)}}"
142
+ }.join(",\n")
143
+ ) + "\n}"
144
+ end
145
+ }.join("\n\n\n")
146
+
147
+ end
data/bin/rbib2html CHANGED
@@ -1,4 +1,4 @@
1
- #! /usr/bin/ruby
1
+ #! /home/bschroed//bin/ruby
2
2
 
3
3
  $:.unshift("~/lib/ruby")
4
4
 
data/bin/rbib2txt CHANGED
@@ -1,4 +1,4 @@
1
- #! /usr/bin/ruby
1
+ #! /home/bschroed//bin/ruby
2
2
 
3
3
  $:.unshift("~/lib/ruby")
4
4
 
@@ -2,8 +2,10 @@ class BibTeX::Parser
2
2
 
3
3
  rule
4
4
 
5
- file : opt_space { result = val[0] }
6
- | opt_space object_list opt_space { result = val[1] }
5
+ file : opt_space_element { result = File.new(Space.new(val[0])) }
6
+ | opt_space_element
7
+ object_list
8
+ opt_space_element { result = File.new(*([val[0]] + val[1] + [val[2]]) ) }
7
9
  ;
8
10
 
9
11
  object_list : object { result = [val[0]] }
@@ -17,7 +19,7 @@ rule
17
19
  | entry { result = val[0] }
18
20
  ;
19
21
 
20
- comment : COMMENT opt_space value { result = [:comment, val[2]] }
22
+ comment : COMMENT opt_space value { result = Comment.new(val[2]) }
21
23
  ;
22
24
 
23
25
  entry : entry_head assignment_list
@@ -60,44 +62,52 @@ rule
60
62
  | SINGLE_ANFZ value_content_single_del SINGLE_ANFZ { result = val[1] }
61
63
  | DOUBLE_ANFZ value_content_double_del DOUBLE_ANFZ { result = val[1] }
62
64
  | WORD
65
+ ;
66
+
67
+ brace : LBRACE
68
+ | RBRACE
69
+ ;
70
+
71
+ anfz : SINGLE_ANFZ
72
+ | DOUBLE_ANFZ
63
73
  ;
64
74
 
65
75
  value_content_single_del : { result = "" }
66
- | value_content SPACE { result << val[1] }
67
- | value_content WORD { result << val[1] }
68
- | value_content COMMA { result << val[1] }
69
- /* | value_content "\\" SINGLE_ANFZ { result << val[1] << val[2]} */
76
+ | value_content general_vc_token { result << val[1] }
77
+ | value_content brace { result << val[1] }
70
78
  | value_content DOUBLE_ANFZ { result << val[1] }
71
- | value_content CHARACTER { result << val[1] }
72
- | value_content AT { result << val[1] }
73
- | value_content LBRACE { result << val[1] }
74
- | value_content RBRACE { result << val[1] }
75
79
  ;
76
80
 
77
81
  value_content_double_del : { result = "" }
78
- | value_content SPACE { result << val[1] }
79
- | value_content WORD { result << val[1] }
80
- | value_content COMMA { result << val[1] }
82
+ | value_content general_vc_token { result << val[1] }
83
+ | value_content brace { result << val[1] }
81
84
  | value_content SINGLE_ANFZ { result << val[1] }
82
- /* | value_content "\\" DOUBLE_ANFZ { result << val[1] << val[2] } */
83
- | value_content CHARACTER { result << val[1] }
84
- | value_content AT { result << val[1] }
85
- | value_content LBRACE { result << val[1] }
86
- | value_content RBRACE { result << val[1] }
87
85
  ;
88
86
 
89
- value_content : { result = "" }
90
- | value_content SPACE { result << val[1] }
91
- | value_content WORD { result << val[1] }
92
- | value_content COMMA { result << val[1] }
93
- | value_content SINGLE_ANFZ { result << val[1] }
94
- | value_content DOUBLE_ANFZ { result << val[1] }
95
- | value_content CHARACTER { result << val[1] }
96
- | value_content AT { result << val[1] }
87
+ value_content : { result = "" }
88
+ | value_content general_vc_token { result << val[1] }
89
+ | value_content anfz { result << val[1] }
97
90
  | value_content
98
91
  LBRACE value_content RBRACE { result << val[1] << val[2] << val[3] }
99
92
  ;
100
93
 
94
+ general_vc_token : SPACE
95
+ | WORD
96
+ | COMMA
97
+ | EQUALS
98
+ | CHARACTER
99
+ | AT
100
+ ;
101
+
102
+ opt_space_element :
103
+ | space_element
104
+ ;
105
+
106
+ space_element : SPACE { result = Space.new(val[0]) }
107
+
108
+ space : SPACE
109
+ ;
110
+
101
111
  opt_space :
102
112
  | SPACE
103
113
  ;
@@ -109,6 +119,34 @@ end
109
119
 
110
120
  module BibTeX
111
121
  Entry = Struct.new(:type, :key, :properties)
122
+
123
+ class Space < String; end
124
+
125
+ class Comment
126
+ def initialize(comment)
127
+ @comment = comment
128
+ end
129
+
130
+ def to_s
131
+ @comment
132
+ end
133
+
134
+ alias :to_str :to_s
135
+ end
136
+
137
+ class File
138
+ def initialize(*elements)
139
+ @elements = elements.compact
140
+ end
141
+
142
+ def elements
143
+ @elements
144
+ end
145
+
146
+ def entries
147
+ @elements.select { | e | e.is_a?Entry }
148
+ end
149
+ end
112
150
  end
113
151
 
114
152
  ---- inner ----
@@ -120,13 +158,13 @@ end
120
158
  def parse( str )
121
159
  @q = []
122
160
 
123
- @yydebug = true
161
+ # @yydebug = true
124
162
 
125
163
  while str.size > 0 do
126
164
  case str
127
165
  when /\A[\t\n\s]+/o
128
166
  @q.push [:SPACE, $&]
129
- when /\ACOMMENT/o
167
+ when /\Acomment/io
130
168
  @q.push [:COMMENT, $&]
131
169
  when /\A\,/o
132
170
  @q.push [:COMMA, $&]
data/papers.bib CHANGED
@@ -184,7 +184,8 @@
184
184
  pages = {70--73},
185
185
  year = 2005,
186
186
  Organization = {IEEE},
187
- note = {A short overview of applications and methods for lip tracking, automated speech recogniton, person recogniton, etc. Pointers to databases with joint AV material and relevant Publications.}
187
+ note = {A short overview of applications and methods for lip tracking, automated speech recogniton, person recogniton, etc. Pointers to databases with joint AV material and relevant Publications.},
188
+ pdf = {}
188
189
  }
189
190
 
190
191
  @Article{seyadarabi:facial,
@@ -195,5 +196,11 @@ NUMBER = 4 ,
195
196
  year = 2004 ,
196
197
  ISSN = {1305-239X},
197
198
  Author = {Hadi Seyedarabi and Ali Aghagolzadeh and Sohrab Khanmohammadi},
198
- note = {Written in very bad english and does not contain too much information. They track feature points in 2D video data using optical flow and use these points to interpolate a triangle mesh. They claim to have a muscle-based model, but that shows nowhere.}
199
+ note = {Written in very bad english and does not contain too much information. They track feature points in 2D video data using optical flow and use these points to interpolate a triangle mesh. They claim to have a muscle-based model, but that shows nowhere.},
200
+ pdf = {}
201
+ }
202
+
203
+ @comment {
204
+ todo:
205
+ pdf = {local/blake_sparse_realtime_tracking.pdf}
199
206
  }
data/test.bib ADDED
@@ -0,0 +1,5 @@
1
+ @comment {
2
+ todo:
3
+ pdf = {local/blake_sparse_realtime_tracking.pdf}
4
+ x
5
+ }
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: rbibtex
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.1
6
+ version: 0.0.2
7
7
  date: 2005-11-09 00:00:00 +01:00
8
8
  summary: A bibtex parsing library written in pure ruby
9
9
  require_paths:
@@ -39,7 +39,9 @@ authors:
39
39
  files:
40
40
  - papers.bib
41
41
  - README
42
+ - test.bib
42
43
  - CHANGELOG
44
+ - InstalledFiles
43
45
  - papers.html
44
46
  - setup.rb
45
47
  - bin