caligrafo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Lucas de Castro
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ = caligrafo
2
+
3
+ Description goes here.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 Lucas de Castro. See LICENSE for details.
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "caligrafo"
8
+ gem.summary = %Q{DSL para geração de arquivos texto.}
9
+ gem.description = %Q{DSL para geração de arquivos texto.}
10
+ gem.email = "castro.lucas@gmail.com"
11
+ gem.homepage = "http://github.com/lucasdecastro/caligrafo"
12
+ gem.authors = ["Lucas de Castro"]
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
16
+ end
17
+
18
+ require 'rake/testtask'
19
+ Rake::TestTask.new(:test) do |test|
20
+ test.libs << 'lib' << 'test'
21
+ test.pattern = 'test/**/*_test.rb'
22
+ test.verbose = true
23
+ end
24
+
25
+ task :default => :test
26
+
27
+ require 'rake/rdoctask'
28
+ Rake::RDocTask.new do |rdoc|
29
+ if File.exist?('VERSION')
30
+ version = File.read('VERSION')
31
+ else
32
+ version = ""
33
+ end
34
+
35
+ rdoc.rdoc_dir = 'rdoc'
36
+ rdoc.title = "caligrafo #{version}"
37
+ rdoc.rdoc_files.include('README*')
38
+ rdoc.rdoc_files.include('lib/**/*.rb')
39
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,51 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{caligrafo}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Lucas de Castro"]
12
+ s.date = %q{2009-10-24}
13
+ s.description = %q{DSL para geração de arquivos texto.}
14
+ s.email = %q{castro.lucas@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "caligrafo.gemspec",
27
+ "lib/caligrafo.rb",
28
+ "test/arquivo_esperado.txt",
29
+ "test/caligrafo_test.rb",
30
+ "test/test_helper.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/lucasdecastro/caligrafo}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.5}
36
+ s.summary = %q{DSL para geração de arquivos texto.}
37
+ s.test_files = [
38
+ "test/test_helper.rb",
39
+ "test/caligrafo_test.rb"
40
+ ]
41
+
42
+ if s.respond_to? :specification_version then
43
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
47
+ else
48
+ end
49
+ else
50
+ end
51
+ end
@@ -0,0 +1,211 @@
1
+ module Caligrafo
2
+ def self.included(base)
3
+ base.instance_eval do
4
+ include InstanceMethods
5
+ end
6
+ end
7
+
8
+ module InstanceMethods
9
+ def criar_arquivo(nome_arquivo, &bloco)
10
+ arquivo = Arquivo.new(nome_arquivo, bloco)
11
+ arquivo.criar_arquivo
12
+ nome_arquivo
13
+ end
14
+ end
15
+
16
+ module Formatador
17
+ def self.formatos
18
+ @@formatos
19
+ end
20
+
21
+ def self.registrar(nome, formatador)
22
+ @@formatos ||= {}
23
+ @@formatos[nome] = formatador.new
24
+ end
25
+
26
+ def self.pesquisar(tipo)
27
+ formatador = @@formatos.values.find { |f| f.tipos.include? tipo }
28
+ formatador ||= @@formatos[:default]
29
+ end
30
+
31
+ class Base
32
+ attr_reader :tipos, :alinhamento, :preenchimento
33
+
34
+ def initialize
35
+ @tipos = []
36
+ @alinhamento = :esquerda
37
+ @preenchimento = ' '
38
+ end
39
+
40
+ def formatar(valor, opcoes = {})
41
+ valor.to_s
42
+ end
43
+
44
+ def preencher(string, tamanho)
45
+ if self.alinhamento == :direita
46
+ string = string.rjust tamanho, self.preenchimento
47
+ else
48
+ string = string.ljust tamanho, self.preenchimento
49
+ end
50
+
51
+ string = string[0..(tamanho - 1)] if string.size > tamanho
52
+ string
53
+ end
54
+ end
55
+
56
+ class Numerico < Base
57
+ def initialize
58
+ @tipos = [Fixnum]
59
+ end
60
+
61
+ def alinhamento
62
+ :direita
63
+ end
64
+
65
+ def preenchimento
66
+ '0'
67
+ end
68
+ end
69
+
70
+ class Decimal < Numerico
71
+ def initialize
72
+ @tipos = [Float]
73
+ end
74
+
75
+ def formatar(valor, opcoes = {})
76
+ ('%.2f' % valor).gsub('.','')
77
+ end
78
+ end
79
+
80
+ self.registrar :default, Base
81
+ self.registrar :numerico, Numerico
82
+ self.registrar :decimal, Decimal
83
+ end
84
+
85
+ class Arquivo
86
+ attr_reader :nome, :bloco
87
+ attr_accessor :objeto, :indice, :linha, :numero_linha, :file
88
+
89
+ def initialize(nome, bloco)
90
+ @nome = nome
91
+ @bloco = bloco
92
+ @linha = ''
93
+ @numero_linha = 1
94
+ end
95
+
96
+ def criar_arquivo
97
+ # Se eu simplesmente chamasse o bloco, os método de Arquivo
98
+ # não estariam disponíveis. ;)
99
+ self.class.send :define_method, :executar_bloco, &bloco
100
+
101
+ self.objeto = bloco.binding.eval "self"
102
+
103
+ File.open(nome, 'w') do |file|
104
+ self.file = file
105
+ executar_bloco
106
+ end
107
+
108
+ nome
109
+ end
110
+
111
+ def secao(nome, &bloco)
112
+ if self.objeto.respond_to? nome
113
+ objetos = self.objeto.send nome
114
+ objetos = [objetos] if objetos.nil? or !objetos.is_a?(Array)
115
+ else
116
+ objetos = [objeto]
117
+ end
118
+
119
+ objetos.each_with_index do |objeto, index|
120
+ self.objeto = objeto
121
+ self.indice = index
122
+ bloco.call objeto
123
+ nova_linha
124
+ end
125
+
126
+ self.objeto = self.bloco.binding.eval "self"
127
+ end
128
+
129
+ def nova_linha
130
+ self.linha = ''
131
+ self.numero_linha += 1
132
+ self.file.print "\n"
133
+ end
134
+
135
+ def imprimir(*args)
136
+ campo = Campo.new(*args)
137
+ valor_campo = campo.valor_para(objeto)
138
+
139
+ posicao = campo.posicao
140
+ if posicao
141
+ valor_campo = valor_campo.rjust(posicao - self.linha.size + 1)
142
+ end
143
+
144
+ self.linha << valor_campo
145
+ self.file.print valor_campo
146
+ end
147
+ end
148
+
149
+ # campo :nome
150
+ # campo :profisao, 'Programador'
151
+ # campo :idade, 46, :posicao => 12
152
+ # campo :tentativas, :alinhamento => :esquerda, :tamanho => 10
153
+ # campo :salario, :formato => :decimal
154
+ # campo 'FIM'
155
+ class Campo
156
+ attr_accessor :nome, :valor, :posicao, :formato, :tamanho, :opcoes_para_formatador
157
+
158
+ def initialize(*args)
159
+ opcoes = (args.last.is_a?(Hash) ? args.pop : {})
160
+ @formato = opcoes.delete(:formato)
161
+ @posicao = opcoes.delete(:posicao)
162
+ @tamanho = opcoes.delete(:tamanho)
163
+ @opcoes_para_formatador = opcoes
164
+
165
+ if args.first.is_a? Symbol
166
+ @nome = args.first
167
+ @valor = args[1]
168
+ else
169
+ @valor = args.first
170
+ end
171
+ end
172
+
173
+ def valor_para(objeto)
174
+ valor = if chamar_metodo?
175
+ begin
176
+ objeto.send(self.nome)
177
+ rescue Exception => e
178
+ raise "Erro ao chamar #{self.nome.inspect} em #{objeto}: #{e.message}"
179
+ end
180
+ else
181
+ self.valor
182
+ end
183
+
184
+ formatar(valor)
185
+ end
186
+
187
+ private
188
+ def chamar_metodo?
189
+ (self.nome && self.valor.nil?)
190
+ end
191
+ def formatar(valor)
192
+ if self.formato
193
+ formatador = Caligrafo::Formatador.formatos[self.formato]
194
+ else
195
+ formatador = Formatador.pesquisar valor.class
196
+ end
197
+
198
+ string = formatador.formatar(valor, self.opcoes_para_formatador)
199
+ string = formatador.preencher(string, self.tamanho) if self.tamanho
200
+ string
201
+ end
202
+ end
203
+ end
204
+
205
+ # TODO criar arquivo de extensoes.
206
+ class ::Fixnum
207
+ def espacos
208
+ ' ' * self
209
+ end
210
+ end
211
+
@@ -0,0 +1,7 @@
1
+ Lucas da Silva 0259000050 1
2
+ Fone#1: 55 86 2222-3333 2
3
+ Fone#2: 55 86 9999-1234 3
4
+ google.com 4
5
+ blip.tv 5
6
+ slideshare.net 6
7
+ FIM 7
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+ require 'caligrafo'
3
+ require 'ostruct'
4
+
5
+ class Telefone < Caligrafo::Formatador::Base
6
+ def formatar(valor, opcoes={})
7
+ valor.gsub(/(\d\d)(\d\d)(\d\d\d\d)(\d\d\d\d)/,'\1 \2 \3-\4')
8
+ end
9
+ end
10
+ Caligrafo::Formatador.registrar :fone, Telefone
11
+
12
+ class Portifolio < OpenStruct
13
+ include Caligrafo
14
+
15
+ def gerar_arquivo(nome_arquivo)
16
+
17
+ criar_arquivo nome_arquivo do
18
+ secao :cabecalho do
19
+ imprimir :nome, :tamanho => 50 # Textos são alinhados à esquerda.
20
+ imprimir :idade, :tamanho => 3 # Números são alinhados à direita com zeros à esquerda.
21
+ imprimir :salario # Decimais possuem duas casas decimais.
22
+ imprimir 5.espacos # Quando o 1º parâmetro não for um símbolo ele será o conteúdo.
23
+ imprimir numero_linha, :posicao => 100 # 'numero_linha' é um método que guarda a linha corrente do arquivo.
24
+ end
25
+
26
+ secao :telefones do |telefone| # telefones é um método. Escreve uma linha pora cada objeto retornado.
27
+ imprimir :descricao, "Fone##{indice + 1}: " # Valor fixo sendo usado como 2º parâmetro.
28
+ # O 1º fica sendo usado apenas para descrição.
29
+ # 'indice' é um método que guarda o indice do elemento no array.
30
+ imprimir telefone, :formato => :fone # Usando um formatador personalizado.
31
+ imprimir numero_linha, :posicao => 100 # posicao é usado para pular para uma coluna. Até lá tudo será vazio (' ').
32
+ end
33
+
34
+ secao :sites do |site|
35
+ imprimir :downcase # Podemos chamar o método do item nas seções.
36
+ imprimir numero_linha, :posicao => 100
37
+ end
38
+
39
+ secao :rodape do
40
+ imprimir 'FIM' # Uma nova linha é criada sempre que saimos ou entramos numa seção.
41
+ imprimir numero_linha, :posicao => 100 # Como não definimos o tamanho, ficará alinhado à esquerda, mesmo sendo número.
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ class CaligrafoTest < Test::Unit::TestCase
48
+ def setup
49
+ @target = 'test/arquivo_gerado.txt'
50
+ end
51
+ def teardown
52
+ File.delete @target rescue nil
53
+ end
54
+
55
+ def test_gerar_arquivo_texto
56
+ pessoa = Portifolio.new :nome => 'Lucas da Silva',
57
+ :idade => 25,
58
+ :salario => 90_000.5,
59
+ :telefones => ['558622223333', '558699991234'],
60
+ :sites => ['Google.com', 'Blip.tv', 'SlideShare.net']
61
+ pessoa.gerar_arquivo @target
62
+
63
+ nome_arquivo_esperado = 'test/arquivo_esperado.txt'
64
+ File.open(nome_arquivo_esperado, 'w') do |file|
65
+ file.puts <<-EOF
66
+ Lucas da Silva 0259000050 1
67
+ Fone#1: 55 86 2222-3333 2
68
+ Fone#2: 55 86 9999-1234 3
69
+ google.com 4
70
+ blip.tv 5
71
+ slideshare.net 6
72
+ FIM 7
73
+ EOF
74
+ end
75
+
76
+ assert_equal_files nome_arquivo_esperado, @target
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'diff/lcs'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'caligrafo'
8
+
9
+ class String
10
+ def first_diff(other)
11
+ self.diff(other).first.first.position rescue nil
12
+ end
13
+ end
14
+
15
+ class Test::Unit::TestCase
16
+ def assert_equal_files(expected, given)
17
+ expected = File.new(expected, 'r') if expected.is_a? String
18
+ given = File.new(given, 'r') if given.is_a? String
19
+
20
+ expected_text = expected.read
21
+ given_text = given.read
22
+
23
+ lines_of_given_text = given_text.lines.to_a
24
+
25
+ expected_text.each_with_index do |line, index|
26
+ begin
27
+ assert_equal line, lines_of_given_text[index]
28
+ rescue Test::Unit::AssertionFailedError => e
29
+ column = Diff::LCS.diff(line, lines_of_given_text[index]).first.first.position + 1
30
+ raise Test::Unit::AssertionFailedError, "Line #{index + 1} dont match on column #{column}:\n#{e.message}"
31
+ end
32
+ if expected_text.to_a.size < given_text.to_a.size
33
+ assert_equal expected_text, given_text
34
+ end
35
+ end
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: caligrafo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lucas de Castro
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-24 00:00:00 -03:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: "DSL para gera\xC3\xA7\xC3\xA3o de arquivos texto."
17
+ email: castro.lucas@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - caligrafo.gemspec
33
+ - lib/caligrafo.rb
34
+ - test/arquivo_esperado.txt
35
+ - test/caligrafo_test.rb
36
+ - test/test_helper.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/lucasdecastro/caligrafo
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: "DSL para gera\xC3\xA7\xC3\xA3o de arquivos texto."
65
+ test_files:
66
+ - test/test_helper.rb
67
+ - test/caligrafo_test.rb