PageRenderTime 88ms CodeModel.GetById 14ms app.highlight 69ms RepoModel.GetById 1ms app.codeStats 1ms

/extras/t2tmake.rb

http://txt2tags.googlecode.com/
Ruby | 464 lines | 239 code | 31 blank | 194 comment | 30 complexity | 904a7f86ece26424fc955705b4aa5ad9 MD5 | raw file
  1#!/usr/bin/env ruby
  2
  3require 'optparse'
  4require 'fileutils'
  5
  6=begin
  7:title: Documentaусo do t2t-make
  8
  9 = t2tmake.rb (0.8beta)
 10 Programa para o processamento automatico de arquivos utilizando
 11 o txt2tags <t2t> (http://txt2tags.org)
 12 
 13 == download e instalaусo
 14 Existem duas maneiras de baixar este programa:
 15 - Na рrea de arquivos da lista[http://groups.yahoo.com/group/txt2tags-br].
 16   dos usuрrios do txt2tags (em portuguЖs)
 17 - Na pрgina[http://txt2tags-win.sourceforge.net/t2tmake.zip] em portuguЖs do txt2tags.
 18
 19 ===requisitos
 20 - txt2tags (ж claro, sem ele este programa nсo existiria);
 21 - ruby 1.6.8+ (ж lзgico, senсo este programa nсo roda);
 22 - python 1.5+ (sim, sim, para o txt2tags rodar);
 23 
 24 ===instalaусo: (t2t)
 25 - txt2tags: verifique o site http://txt2tags.org;
 26 - python: verifique o site www.python.org;
 27 
 28 ===instalaусo (ruby)
 29 - Windows:
 30   Baixe de http://rubyinstaller.sourceforge.net e execute o
 31   programa de instalaусo.
 32 - Linux:
 33   A maioria das grandes distribuiушes jр possuem o pacote em
 34   algum CD. Siga os procedimentos normais de instalaусo. Caso
 35   nсo exista para a sua, baixe os fontes de
 36   http://www.ruby-lang.org/en/ e siga os procedimentos.
 37 - Mac OSX:
 38   As versшes atuais jр trazem o Ruby. Caso contrрrio seria
 39   necessрrio baixar os fontes de http://www.ruby-lang.org/en/
 40   e compilar.
 41 - Cygwin:
 42   Rode o programa de setup, e instale a versсo compilada do
 43   Ruby (1.6.8).
 44 - Outros:
 45   Nсo tenho idжia. Sз vendo.
 46 
 47 ===instalaусo (programa)
 48 - apenas copie o programa para o local de sua preferЖncia (em
 49   um local onde ele possa ser executado sem especificar o
 50   caminho ж uma boa idжia)
 51 
 52 ==caracterьsticas
 53 - processa apenas os arquivos necessрrios (atualizados ou inexistentes);
 54 - permite o processamento recursivo (subdiretзrios);
 55 - gera log dos arquivos para facilitar a atualizaусo de sites;
 56 - roda em Windows, Linux, Cygwin, (etc?)
 57 - opусo para adequaусo de indexes localizados para o Apache,
 58   index-ptbr.t2t => index.html.ptbr
 59 - aceita opушes a partir de um arquivo de configuraусo (+veja observaушes abaixo+)
 60 - permite listar os rзtulos existentes no arquivo de configuraусo  
 61
 62 ===Obs: 
 63 ==== --batch filename rзtulo
 64 - deve ser a Щltima opусo da linha de comando
 65 - as opушes anteriores mantidas sсo: --clean --all
 66 - o arquivo contendo as opушes ж um arquivo texto no seguinte formato:
 67 - os rзtulos devem estar entre chaves
 68 - deixar uma linha em branco para separar os rзtulos
 69 - caminhos contendo espaуoes deverсo estar entre aspas "caminho"
 70	[rotulo]
 71	--opусo
 72	...
 73	--opусo
 74 ex.:
 75
 76 [txt2tags-win]
 77 --L10N
 78 --type html
 79 --sdir "C:/Arquivos de programas/Apache Group/Apache/htdocs/txt2tags-win"
 80 --ddir "C:/Arquivos de programas/Apache Group/Apache/htdocs/txt2tags-win"
 81 -r
 82
 83
 84 ==por fazer:
 85 - inclusсo de opушes de pesquisa (--todo e --find text|ER)
 86 - inclusсo de opушes de alteraусo (--subs texto:texto)
 87 - aceitar outras opушes para enviar ao t2t
 88 - ??
 89 
 90 = copyright
 91 (C) 2003 por Guaracy Monteiro (http://ruby-ptbr.rubyforge.org/)
 92 
 93 = licenуas
 94 GPL + Ruby (ou seja, faуa o uso que desejar)
 95 
 96 = historico
 97 [A]lteraусo; Correусo de [B]ugs; [N]ovo
 98
 99 25/08/2003
100 - lanуamento (testes iniciais no Mandrake 9.1 e Windows 2000 utilizando
101   ruby 1.8 e no Cygwin utilizando ruby 1.6.8)
102 30/08/2003
103 - [A]alteraушes nos comentрrios do programa para a geraусo automрtica 
104   da documentaусo pelo rdoc;
105 - [A]alteraушes em nomes de variрveis e mжtodos do programa
106   bem como de opушes aceitas pelo mesmos e respectivas rotinas;
107 - [B]passagem de diretзrio com espaуos para o txt2tags;
108 - [N]opусo L10N para arquivos de indices do Apache. Executada
109   apenas para --type html
110   index-en.t2t, index-ptbr.t2t => index.html.en, index.html.ptbr;
111 - [N]opусo --batch filename label. Abre um arquivo de configuraусo
112   (default => t2t-make.conf), procura pelo rзtulo especificado e
113   passa para a linha de comandos as opушes encontradas no arquivo
114   (encerra na primeira linha em branco);
115 - [N]opусo -L. Utilizada em conjunto com a opусo --batch e serve
116   para apenas listar os rзtulos encontrados no arquivo sem a
117   execuусo do mesmo;
118 - [A]separaусo da rotina para interpretar a linha de comandos
119   para facilitar a execuусo de arquivos de lotes;
120 - [N]opусo --ext extensсo para gerar arquivo com extensсo
121   diferente da padrсo;
122 - [N]opусo --all para forуar a atualizaусo de todos os arquivos
123 09/07/2004
124 - [A]correушes diversas para atualizaусo
125 10/07/2004
126 - [A]utilizaусo de optparse para verificaусo das opушes
127 - [A]exclusсo do parРmetro -L
128 - [N]parРmetro -b/--batch lista rзtulo em caso de omissсo ou erro
129 - [A]alteraусo dos mжtodos para tratamento de arquivos batch
130 - [N]lanуamento da versсo 1.0rc
131 - [A]exclusсo do mжtodo usage (incorporado na verificaусo dos parРmetros)
132 - [A]alteraушes em diversas partes do programa por conta da 'optparse'
133 - [N]ж salvo a data e os dados sсo adicionados no logfile
134=end
135
136# versсo do programa
137$VERSAO = "1.0rc"
138
139#++ >> ATENК├O <<
140# A constante $T2T contжm o caminho para o txt2tags e
141# deve ser alterada conforme o seu sistema
142# Alguns exemplos:
143# $T2T = 'python C:/utils/txt2tags.py'
144# $T2T = 'E:/utils/txt2tags/txt2tags.exe'
145# $T2T = /usr/local/bin/txt2tags
146
147if RUBY_PLATFORM =~ /mswin/
148  $T2T = 'C:/Arquivos de programas/txt2tags/txt2tags.exe'
149  $POPEN = true
150else
151  $T2T = 'txt2tags'
152  $POPEN = true #false
153end
154
155$flags = ''
156
157$IDX_SRC = 0		# indice para caminho dos fontes
158$IDX_DSTDIR = 1		# indice para caminho dos destinos
159$IDX_DSTFILE = 2	# indice para nome do arquivo destino
160
161
162# Tipos vрlidos para o txt2tags
163$tipos = %w(html xhtml sgml tex man mgp moin pm6 txt)
164
165# Mostra uma mensagem de erro e aborta o programa
166# ---
167def abort(msg)
168  puts "Abnormal program termination!"
169  puts msg
170  exit
171end
172
173# Retorna uma string com a versсo do programa
174# ---
175def version
176  print "\nt2tmake.rb version #{$VERSAO}\n"
177  print "(c) 2003 by Guaracy B. Monteiro\n\n"
178end
179
180
181# Pesquisa um diretзrio e executa um bloco passado para
182# cada arquivo que coincidir com a mрscara especificada
183# Se _recursive_ for igual a +verdadeiro+, a pesquisa
184# serр efetuada em toda a рrvore do diretзrio informado
185#---
186def dir_recurse(dirname, mask, recursive, &action)
187  d = Dir.pwd
188  Dir.chdir(dirname)
189  Dir["#{mask}"].each do |file|
190    action.call("#{dirname}/#{file}")
191  end
192  return if !recursive
193  Dir.open(dirname) do |dir|
194    dir.each do |file|
195      if FileTest.directory?("#{dirname}/#{file}")
196        next if file =~ /^\.\.?$/
197        dir_recurse("#{dirname}/#{file}", mask, recursive, &action)
198      end
199    end
200  end
201  Dir.chdir(d)
202end
203
204# Recebe uma matriz com o caminho completo e nome dos 
205# arquivos, a especificaусo do diretзrio original, a 
206# especificaусo do diretзrio destino e o tipo (extensсo) 
207# dos arquivos destinos.
208# Retorna uma matriz onde cada elemento contжm:
209# - caminho completo e nome dos arquivos de origem
210# - caminho completo do destino
211# - nome e extensсo do arquivo destino correspondente
212# ---
213def gen_destfiles(files, srcdir, dst_dir, type)
214  basedir = srcdir.size
215  files.collect do |filedir|
216    dir = dst_dir + File.dirname(filedir)[basedir..-1]
217    file = File.basename(filedir,'.t2t')
218    if !@l10n.nil?
219      if type == 'html' and file =~ /^index\-/
220        file = file.split('-',2)
221        file = sprintf("%s.%s.%s", file[0] , type, file[1])
222      else
223        file << ".#{type}"
224      end
225    else
226      file << ".#{type}"
227    end
228    [filedir, dir, file]
229  end
230end
231
232# Rotina para a verificar se o arquivo fonte ж mais
233# atual que o arquivo destino ou se este nсo existe.
234# Se for confirmada a condiусo, o programa executarр
235# o txt2tags para que a atualizaусo do destino seja
236# feita, bem como irр gravar no arquivo +logfile+ o
237# caminho completo e nome do arquivo destino que
238# foi alterado.
239# ---
240def make(files, logfile)
241  if !@log_fn.nil?
242		logfile = File.new(logfile,"a") 
243		logfile.puts Time.new.strftime("# %c\n")
244	end
245  files.each do |data|
246    src = data[$IDX_SRC]
247    dstdir = data[$IDX_DSTDIR]
248    dst = "#{dstdir}/#{data[$IDX_DSTFILE]}"
249    begin
250      if !FileTest.exist?(dstdir)
251			  FileUtils.mkdir_p(dstdir)
252      end
253    rescue => erro
254      abort("Can't create directory - #{dstdir}")
255    end
256    if !@all.nil? or !File.exist?(dst) or File.stat(src).mtime > File.stat(dst).mtime
257      puts "Processing - #{src}"
258      cmd = "\"#{$T2T}\" #{$flags} -o \"#{dst}\" \"#{src}\""
259      if $POPEN
260        IO.popen(cmd) { |res|
261          puts res.readlines
262        }
263      else
264        if !system(cmd)
265          abort("Error while executin - '#{$T2T}'")
266        end
267      end
268      logfile.puts dst if !@log_fn.nil?
269    else
270      puts"Nothing to be done for - #{data[$IDX_DSTFILE]} #{src}"
271    end
272  end
273end
274
275# Remove todos os arquivos com uma determinada
276# extensсo em um diretзrio destino baseado em
277# uma lista de arquivos fontes especificadas
278# ---
279def clean(files, type, dst_dir)
280  puts "Cleaning..."
281  files.each do |data|
282    dst = "#{data[$IDX_DSTDIR]}/#{data[$IDX_DSTFILE]}"
283    if File.exist?(dst)
284      puts "deleting - #{dst}"
285      File.delete(dst)
286    end
287  end
288end
289
290# Mostra rзtulos vрlidos em arquivo batch e encerra
291# ---
292def abort_batch_labels(conf_file, data, msg)
293    puts msg unless msg.empty?
294    puts "Valid labels for #{conf_file}:"
295    data.each do |line|
296      puts "#{line}" if line =~ /^\[.+\]\s*/ 
297    end
298    exit
299end
300
301# Pocessamento de arquivos com instruушes
302# ---
303def batch(file,label,msg="")
304  conf_file = File.expand_path(file)
305  conf_file += "/t2t-make.conf" if FileTest.directory?(conf_file)
306  if !FileTest.exist?(conf_file)
307    puts "Can't find file #{conf_file}"
308    exit
309  end
310  data = IO.readlines(conf_file)
311  data.collect! do |linha| linha.chop end
312  if label.nil?
313    abort_batch_labels(conf_file,data,msg)
314  end
315  idx = data.index("[#{label}]")
316  if idx.nil?
317    abort_batch_labels(conf_file,data,"Can't find label - '#{label}'")
318  end
319  for i in (idx+1)..(data.size-1)
320    break if data[i] == ''
321    abort("Malformated line\nfile : #{conf_file}\nlabel : [#{label}]\nline -  #{data[i]}\nin") if data[i] !~ /^\-/
322      ARGV << data[i].split(nil,2)
323  end
324  ARGV.flatten!
325end
326
327# Rotina principal do programa, encarregada de verificar
328# os argumentos especificados na linha de comando.
329# ---
330def parse_args
331    ARGV.options do
332      |opts|
333      opts.on_tail
334      opts.on_tail("common options:")
335      opts.on_tail("-h", "--help", "show this message") do
336        puts opts
337        exit
338      end
339      opts.on_tail("-V", "--version", "show version") do
340        puts "t2tmake #{$VERSION}"
341        exit
342      end
343      opts.on_head("specific options:")  
344      opts.on("-t", "--type=TARGET", String, "set target (txt2tags) document type",$tipos.join(",")) do |x|@type=x
345        if !@type.nil?
346          if !$tipos.include?(@type)
347            puts "'#{@type}' is not a valid target type. Valid types are:"
348            puts $tipos.join(' | ')
349            exit
350          end
351        end
352      end
353      # formal argument cannot be an instance variable: {|@ext|}
354      opts.on("-e", "--ext=EXT", String, "set output file extension") {|x|@ext=x}
355      opts.on("-r", "--recusive", "recursive directory processing.") {|x|@recursive=x}
356      opts.on("-s", "--sdir=DIR", String, "especify source directory","default => actual_directory (pwd)") {|x|@src_dir=x}
357      opts.on("-d", "--ddir=DIR", String, "set target directory","default => actual_directory./_<type>") {|x|@dst_dir=x}
358      opts.on("-l", "--log[=FILE]", "log changes (processed files)","default => target_directory/t2tmake.log") {|x|@log_fn=x;@log_fn ||= ''}
359      opts.on("--L10N", "Apache localization", "index-en.t2t => index.html.en") {|x|@l10n=x}
360      opts.on("-a", "--all", "force to process all files") {|x|@all=x}
361      opts.on("-c", "--clean", "erase all target files before processing") {|x|@clean=x}
362      opts.on("-b", "--batch=FILE[,LABEL]",Array,"use options from an specified 'label'","stored in a batch file;","without LABEL, list all labels") do |x,y|@batch,@label=x,y
363        if @label.nil?
364          batch(@batch,@label,"No label specified.")
365          exit
366        end
367      end
368      opts.parse!
369    end
370end
371
372# Verificar a validade dos argumentos passados para o programa
373# e toma as providencias necessрrias como ajustar nomes de 
374# diretзrios, montar a lista de arquivos e chamar o mжtodo 
375# responsрvel para execuусo dos procedimentos desejados pelo 
376# usuрrio.
377# ---
378def main
379  # warning: instance variable @foo not initialized
380  @batch = nil
381  @type = nil
382  @src_dir = nil
383  @dst_dir = nil
384  @ext = nil
385  @recursive = nil
386  @clean = nil
387  @log_fn = nil
388  @log_fn = nil
389
390#  if ARGV.empty?
391#    ARGV.push("--help")
392#  end
393  fbatch = false
394  while true do
395    parse_args
396    if !@batch.nil?
397      abort("Nested batch files not allowed.") if fbatch
398      ARGV.clear
399      batch(@batch,@label)
400      @batch=nil
401      fbatch = true
402      next
403    else
404      break
405    end
406  end
407	
408	@type='html' if @type.nil?
409	
410  if @src_dir.nil?
411    src_dir = Dir.pwd
412  else
413    src_dir = @src_dir.gsub(/[\"\']/,'')
414    src_dir = File.expand_path(src_dir)
415  end
416	
417  if @dst_dir.nil?
418    dst_dir = src_dir + "/_#{@type}"
419  else
420    dst_dir = @dst_dir.gsub(/[\"\']/,'')
421    dst_dir = File.expand_path(dst_dir)
422  end
423  if !FileTest.exist?(dst_dir)
424		FileUtils.mkdir_p(dst_dir)
425  end
426
427  files = []	
428	
429  ext = (@ext.nil?) ? (@type) : (@ext)
430  dir_recurse(src_dir, "*.t2t", !@recursive.nil?) { |file| files << file }
431  files = gen_destfiles(files, src_dir, dst_dir, ext)
432  if !@clean.nil?
433    clean(files, type, dst_dir)
434    return
435  end
436	if !@log_fn.nil?
437		logfile = (@log_fn.empty?) ? ("#{dst_dir}/t2tmake.log") : (File.expand_path(@log_fn))
438		if !FileTest.exist?(File.dirname(logfile))
439			begin
440				Dir.mkdir("#{File.dirname(logfile)}")
441			rescue => erro
442				abort("#{erro}\nCan't create logfile - #{logfile}")
443			end
444		end
445	else
446		logfile = ""
447	end
448
449  make(files, "#{logfile}")
450	
451end
452
453
454=begin
455
456  #clean nсo usa log
457  $flags = $flags + "-t #{$OPT_type} "
458  end
459=end
460
461# inicio do programa
462main
463puts "Done."
464