#!/usr/bin/ruby #scvim_make_help #Written by Alex Norman for scvim with help from John Yates and Andrzej Kopec #This script uses the apps (unhtml or links) and urtf, it does some wrapping around unhtml #because that doesn't remove the stuff from html .. #it also wraps unrtf because it has some bugs # #it removes the unhtml formatting and puts the results in the specified directory #you can edit these if you know what you're doing #use links for default unhtml [otherwise use "unhtml"] #the trade off is that links might provide nicer output sometimes but it breaks #up paragraphs with newlines so if you have a small help window [width wise] the #text will look lame # # #Copyright 2007 Alex Norman # #This file is part of SCVIM. # #SCVIM is free software: you can redistribute it and/or modify #it under the terms of the GNU General Public License as published by #the Free Software Foundation, either version 3 of the License, or #(at your option) any later version. # #SCVIM is distributed in the hope that it will be useful, #but WITHOUT ANY WARRANTY; without even the implied warranty of #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #GNU General Public License for more details. # #You should have received a copy of the GNU General Public License #along with SCVIM. If not, see . $uselinks = false scvim_cache_dir = ENV["SCVIM_CACHE_DIR"] if !scvim_cache_dir or scvim_cache_dir=="" scvim_cache_dir = File.join(ENV["HOME"],".scvim") else scvim_cache_dir.sub!(/\/$/,"") end #if the cache dir doesn't exist, create it if not File.exists?(scvim_cache_dir) Dir.mkdir(scvim_cache_dir) end help_dest = File.join(scvim_cache_dir, "/doc/") help_tags_file = File.join(help_dest, "TAGS_HELP") help_completion_file = File.join(help_dest, "sc_help_completion") $unhtml = "unhtml" $unrtf = "unrtf" help_source_list = Array.new require 'open3' require 'tempfile' require 'optparse' #create a new hash for the help helphash = Hash.new; def deleteRecursively(items_to_del) items_to_del.each {|x| if File.stat(x).directory? new_items_to_del = Dir.entries(x) new_items_to_del.delete("."); new_items_to_del.delete(".."); new_items_to_del.delete(".svn") new_items_to_del.collect! {|i| "#{x}/" + i } deleteRecursively(new_items_to_del) Dir.unlink(x) else File.delete(x) end } end def deleteEmptyDirs(basedir) basedir.each {|x| if File.stat(x).directory? items_to_del = Dir.entries(x) items_to_del.delete("."); items_to_del.delete(".."); items_to_del.delete(".svn") items_to_del.collect! {|i| "#{x}/" + i } #first check any subdirs if there are any if items_to_del != [] deleteEmptyDirs(items_to_del) items_to_del = Dir.entries(x) items_to_del.delete("."); items_to_del.delete(".."); items_to_del.delete(".svn") if items_to_del == [] Dir.unlink(x) end else Dir.unlink(x) end end } end def runhtml(file) File.open(file, "r"){|f| lines = f.readlines bodyStart = 0 #ditch the header because unhtml doesn't deal with it well (0..lines.size - 1).each do |i| bodyStart = i if lines[i] =~ /\s*$/ tmp << i end } #close everything stdout.close; stderr.close return tmp } return [] end def myunrtf(infile,outfile) tf = Tempfile.new("scvim_unrtfing") tf2 = Tempfile.new("scvim_unrtfing") File.open(infile,"r") { |f| #work around unrtf's lame exclusion of brackets while !f.eof line = f.gets line.gsub!(/\\\{/,"OPENBRACKET") line.gsub!(/\\\}/,"CLOSEBRACKET") line.gsub!(/\\\\/,"SLASH") tf.puts line end } #close the temp file tf.close(false) tf2.close(false) system("#{$unrtf} --text #{tf.path} > #{tf2.path} 2> /dev/null") tf2.open File.open(outfile,"w") { |f| #work around unrtf's lame exclusion of brackets count = 0 while !tf2.eof line = tf2.gets #if the line isn't a comment if line !~ /^\s*###/ #remove the blank line and line with ----- at they are there if(!(count < 2 && (line !~ /^\s*$/ || line !~ /^-+/))) line.gsub!(/OPENBRACKET/,"{") line.gsub!(/CLOSEBRACKET/,"}") line.gsub!(/SLASH/,"\\") if line.gsub!(/###.*$/,"") line.chomp! end f.print line end count += 1 end end } end def myunhtml(infile,outfile) if $uselinks lines = IO.popen("links -dump -width 128 'file://#{infile}'").readlines #remove annoying spaces at beg of each line, first see if they are there hasAnnoyingSpaces = true lines.each do |line| if line !~ /^\s{3,}/ and line !~ /^\s*$/ hasAnnoyingSpaces = false break end end if hasAnnoyingSpaces oldlines = lines lines = Array.new oldlines.each do |line| lines << line.sub(/^\s{3,3}/, "") end end File.open(outfile, "w") { |f| f.puts lines } else File.open(outfile, "w") { |f| f.puts runhtml(infile) } end end def processFiles(files_to_process, basedir, helphash, destdir) files_to_process.each{|file| dir = "#{basedir}/" + file if File.stat(dir).directory? if file !~ /CVS|\.svn/ if file =~ /\.rtfd/ #remove the .rtf helpitem = file.sub(/\.rtfd/,"") #if it is suffixed with ".help" remove that helpitem.sub!(/\.help/,"") #remove whitespace helpitem.gsub!(/\s+/, "_") output_helpfile = File.join(destdir, "#{helpitem}.scd") #see if there is a file here, if !File.exists?(output_helpfile) && helphash.key?(helpitem) puts "** #{helpitem} has multiple files associated with it, overwriting the old one" end if File.exists?("#{basedir}/#{file}/TXT.rtf") myunrtf("#{basedir}/#{file}/TXT.rtf",output_helpfile) helphash[helpitem] = output_helpfile end else dirfiles = Dir.entries(dir) dirfiles.delete("."); dirfiles.delete("..") newdestdir = File.join(destdir, file) newdestdir.gsub!(/\s+/, "_") #we must make this directory if it doesn't already exist if !File.exists?(newdestdir) Dir.mkdir(newdestdir) elsif !File.stat(newdestdir).directory? puts "There is a filename that exists that we want to be a directory: #{newdestdir}, exiting\n" exit -1 end processFiles(dirfiles, dir, helphash, newdestdir) end end else if file =~ /\.rtf/ #remove the .rtf helpitem = file.sub(/\.rtf/,"") #if it is suffixed with ".help" remove that helpitem.sub!(/\.help/,"") #remove whitespace helpitem.gsub!(/\s+/, "_") output_helpfile = "#{destdir}/#{helpitem}.scd" #see if there is a file here that is already up to date if !File.exists?(output_helpfile) && helphash.key?(helpitem) puts "** #{helpitem} has multiple files associated with it, overwriting the old one" end myunrtf(File.join(basedir,file), output_helpfile) helphash[helpitem] = output_helpfile elsif file =~ /\.htm[l]?/ #remove the .html helpitem = file.sub(/\.htm[l]?/,"") #if it is suffixed with ".help" remove that helpitem.sub!(/\.help/,"") #remove whitespace helpitem.gsub!(/\s+/, "_") output_helpfile = File.join(destdir, "#{helpitem}.scd") #see if there is a file here that is already up to date if !File.exists?(output_helpfile) && helphash.key?(helpitem) puts "** #{helpitem} has multiple files associated with it, overwriting the old one" end myunhtml(File.join(basedir,file), output_helpfile) helphash[helpitem] = output_helpfile elsif file =~ /\.scd/ output_helpfile = "#{destdir}/#{file}" helpitem = file.sub(/\.scd/,"") #remove whitespace helpitem.gsub!(/\s+/, "_") if !File.exists?(output_helpfile) && helphash.key?(helpitem) puts "** #{helpitem} has multiple files associated with it, overwriting the old one" end system("cp '#{basedir}/#{file}' '#{output_helpfile}'") helphash[helpitem] = output_helpfile end end } end # process the parsed options clean = false confirmthings = true linksDefaultHtml = $uselinks opts = OptionParser.new do |opts| # Mandatory argument. opts.on("-s", "--source-dir directory", "A Source Directory for Help Files", "you can use this many times to give more than one source directory") do |dir| help_source_list.push(dir) end opts.on("-d", "--dest-dir directory", "The Destination Directory for the processed Help Files", "(defaults to #{help_dest})") do |dir| help_dest = dir end # Boolean switch. opts.on("-c", "--clean", "Clean the Destination Directory before building the helpfiles") do |c| clean = c end # Boolean switch. opts.on("-f", "--force", "Do not prompt to see if the user is sure about deleting files") do |y| confirmthings = !y end if linksDefaultHtml explain = "Use links to remove html formatting [default]" else explain = "Use links to remove html formatting" end # Boolean switch. opts.on("-l", "--links", explain) do |c| $uselinks = c end # Boolean switch. if not linksDefaultHtml explain = "Use unhtml to remove html formatting [default]" else explain = "Use unhtml to remove html formatting" end opts.on("-u", "--unhtml", explain) do |c| $uselinks = !c end # No argument, shows at tail. This will print an options summary. opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end begin opts.parse!(ARGV) rescue => e STDERR.puts e STDERR.puts opts exit end if help_source_list.length == 0 puts "\n**You must provide at least one help Source Directory**\n\n" puts opts exit end #make sure the dest dir is valid if !File.exists?(help_dest) if(confirmthings) puts "Help Destination does not exist, should it be created? [yes/no]" responce = STDIN.readline responce.chomp! responce.gsub!(/\s*/,"") end if (!confirmthings) || responce == "y" || responce == "yes" newdirs = help_dest.split("/") if newdirs[0] = "" newdirs[1] = "/" + newdirs[1] newdirs = newdirs[1,newdirs.length] end basedir = "" newdirs.each{ |dir| basedir += "/#{dir}" if !File.exists?(basedir) Dir.mkdir(basedir) elsif !File.stat(basedir).directory? puts "#{basedir} exists but is not a valid directory, please supply a valid Destination directory\n" end } else puts "Responce was not yes, aborting" exit end elsif !File.stat(help_dest).directory? puts "Help Destination is not a directory, please supply a valid directory\n\n" puts opts exit end #make sure that the sources are valid help_source_list.each { |help_source| if !File.exists?(help_source) || !File.stat(help_source).directory? puts "Help Source #{help_source} is not a directory, please supply a valid directory\n\n" puts opts exit end } #clean, removes everything from the help_destination, including the TAGS_HELP and sc_help_completion files if clean if(confirmthings) puts "Clean option, will delete contents of #{help_dest}, are you sure you want to do this? [yes/no]" responce = STDIN.readline responce.chomp! responce.gsub!(/\s*/,"") end if (!confirmthings) || responce == "y" || responce == "yes" puts "Deleting contents of #{help_dest}" items_to_del = Dir.entries(help_dest) #remove . and .. and .svn items_to_del.delete('.'); items_to_del.delete('..') ; items_to_del.delete('.svn') items_to_del.delete('SCVim.scd') #add the path to the file names items_to_del.collect! {|x| "#{help_dest}/" + x } deleteRecursively(items_to_del) else puts "Responce was not yes, aborting" exit end else #something intelligent should be said here about when new files will be created in the destdir end #read in the existing tags, if there are any, and add them to the help hash if File.exists?(help_tags_file) File.open(help_tags_file, "r"){ |tags_file| tags_file.each {| line | line = line.split("\t") helphash[line[0].sub(/SC:/,"")] = line[1] } } end help_source_list.each { |help_source| puts "Grabbing Help from: #{help_source},\n\tprocessing it and putting it here: #{help_dest}" #get orig dir and chdir to the source orig_dir = Dir.pwd Dir.chdir(help_source) #find the files/directories in the source directory files = Dir.entries(help_source) files.delete('.') ; files.delete('..'); files.delete('.svn') #actually process the files [recursively] processFiles(files, ".", helphash, help_dest) #change directories back Dir.chdir(orig_dir) } #add SCVim.scd into the help output if it doesn't already exist there if not helphash["SCVim"] helphash["SCVim"] = "SCVim.scd" end #write out the tags and completion files completion = File.open(help_completion_file, "w") File.open(help_tags_file, "w"){ |tags_file| helphash.sort.each {| key, val | val.sub!(/^#{help_dest}\//,"") tags_file.puts "SC:#{key}\t#{val}\t/^" #put the key into the completion file completion.puts key } } completion.close #delete empty directories items_to_check = Dir.entries(help_dest) #remove . and .. items_to_check.delete("."); items_to_check.delete(".."); items_to_check.delete(".svn") items_to_check.collect! {|x| "#{help_dest}/" + x } deleteEmptyDirs(items_to_check) puts "Done"