1#!/usr/bin/env ruby 2# 3# Internal helper script to create a markdown file from binaries 4# 5# The --index option creates the index page 6# 7# bin2md [--index] erbtemplate [binary] 8# 9# by Pjotr Prins (C) 2020 10# 11# The rules are simple USAGE: 12# 13# usage: can be multiline block anywhere in the output 14# 15# After removing that the next block is the DESCRIPTION. 16# Onle line create a TYPE (see TYPES). 17# The rest are the OPTIONS. 18 19require 'erb' 20require 'date' 21require 'open3' 22 23# cerr << endl << "Type: statistics" << endl << endl; 24# cerr << endl << "Type: transformation" << endl << endl; 25TYPES = ["filter","metrics","phenotype","genotype","transformation","statistics"] 26 27=begin 28 29if (argc == 2) { 30 string h_flag = argv[1]; 31 if (h_flag == "-h" || h_flag == "--help") { 32 cerr << R"( 33Generate a random VCF file 34 35Usage: vcfrandom 36 37Example: 38 39 vcfrandom 40 41 42Type: statistics 43 44 )"; 45 exit(1); 46 } 47 } 48 49=end 50 51 52VERSION=`cat ./VERSION`.strip 53template = ARGV.shift 54is_man = false # creating man pages? 55if template == "--man" 56 is_man = true 57 template = ARGV.shift 58end 59create_index = false 60if template == "--index" 61 create_index = true 62 template = ARGV.shift 63 index = [] 64end 65search = ARGV.shift 66 67bindir = './build' 68$stderr.print("--- Parsing the bin files in #{bindir} for #{VERSION}\n") 69 70d = DateTime.now 71year = d.year 72 73Dir.glob(bindir+'/*').each do|bin| 74 if !File.directory?(bin) and File.executable?(bin) 75 if search and bin !~ /#{search}/ 76 next 77 end 78 cmd = File.basename(bin) 79 help_cmd = cmd + " -h" 80 $stderr.print(" "+bin+"\n") 81 stdout, stderr, status = Open3.capture3(bin+" -h") 82 out = stderr + stdout 83 if out == "" 84 help_cmd = cmd 85 stdout, stderr, status = Open3.capture3(bin) 86 out = stderr + stdout 87 end 88 # out = ,:encoding => 'UTF-8' 89 out = out.encode('UTF-8') 90 # $stderr.print(out) 91 lines = (out).split("\n") 92 lines = lines.map{|l| l.gsub(/#{Regexp.escape(cmd)}/,"**#{cmd}**")} 93 lines = lines.map{|l| l.gsub(/\.+\/build\//,"")} 94 lines = lines.map{|l| l.gsub(/INFO: help:?/,"")} 95 lines = lines.map{|l| l.gsub(/INFO: description:/,"")} 96 lines = lines.map{|l| l.gsub(/INFO:\s+/,"")} 97 pydoc_full = lines.map{|l| l=="" ? '>' : l }.join("\n") 98 in_usage = false 99 has_options = nil 100 has_example = false 101 usage = [] 102 other = [] 103 example = [] 104 lines.shift while lines[0] == "" 105 lines.each do | l | 106 break if l == "------------------------------------------------------" 107 if l =~ /usage/i 108 in_usage = true 109 end 110 if in_usage 111 if l == "" or l =~ /^Output/i 112 in_usage = false 113 next 114 end 115 usage << l 116 else 117 if l =~ /^Example:/ 118 has_example = true 119 end 120 if has_example 121 example << l 122 else 123 other << l 124 end 125 end 126 end 127 descr = [] 128 rest = other 129 type = "unknown" 130 (other+example).each do | l | 131 if l =~ /type: (\S+)/i 132 type = $1 133 raise "Unknown type #{type} for #{cmd}" if !TYPES.include?(type) 134 break 135 end 136 end 137 138 other.each do | l | 139 break if l == "" or l =~ /^Output/i or l =~ /Options/i 140 descr << l 141 end 142 143 if descr == [] 144 lineno = 0 145 rr = rest.reverse 146 rr.each_with_index do | l,i | 147 if l != "" and l !~ /^Type/i 148 lineno = i 149 break 150 end 151 end 152 rr = rr[lineno..-1] 153 rr.each do | l | 154 if descr.length and l == "" or l =~ /^\s/ 155 descr = descr.reverse 156 break 157 end 158 descr << l 159 end 160 rest = rr.drop(descr.size).reverse 161 else 162 rest = rest.drop(descr.size) 163 end 164 165 body = rest.join("\n") 166 has_options = true if body != "" 167 usage = usage.join(" ").gsub(/#{VERSION}\s+/,"") 168 usage = usage.gsub(/usage:\s+/i,"") 169 usage = usage.gsub(/\s+/," ").strip 170 pydoc_full = pydoc_full.gsub(/#{VERSION}\s+/,"") 171 pydoc_full = pydoc_full.gsub(/\.\.\/build\//,"") 172 # pydoc_full = pydoc_full.gsub(/vcflib/,"VCF") 173 descr = descr.join(" ").gsub(/#{VERSION}\s+/,"") 174 descr = descr.sub(/vcflib/,"VCF") 175 descr = descr.gsub(/\s+/," ").strip 176 example = example.join("\n") 177 # print("HELP:",help_cmd,"\n") 178 # print("DESCRIPTION:",descr,"\n") 179 # print("USAGE:",usage,"\n") 180 # print("TYPE:",type,"\n") 181 # print("BODY:",body,"\n") 182 183 if create_index 184 rec = { 185 cmd: cmd, 186 type: type, 187 descr: descr 188 } 189 index << rec 190 else 191 b = binding 192 renderer = ERB.new(File.read(template)) 193 194 File.open("./doc/#{cmd}.md","w") { |f| 195 f.print renderer.result(b) 196 } 197 end 198 end 199end 200if create_index 201 require 'ostruct' 202 203 renderer = ERB.new(File.read("./test/scripts/index-item.erb")) 204 File.open("./doc/vcflib.md","w") { |f| 205 f.print <<HEADER 206% vcflib(1) vcflib | vcfilb (index) 207% Erik Garrison and vcflib contributors 208 209# NAME 210 211**vcflib** index 212 213# DESCRIPTION 214 215vcflib contains tools and libraries for dealing with the Variant Call 216Format (VCF) which is a flat-file, tab-delimited textual format 217intended to describe reference-indexed variations between 218individuals. 219 220VCF provides a common interchange format for the description of 221variation in individuals and populations of samples, and has become 222the defacto standard reporting format for a wide array of genomic 223variant detectors. 224 225vcflib provides methods to manipulate and interpret sequence variation 226as it can be described by VCF. It is both: 227 228* an API for parsing and operating on records of genomic variation as it can be described by the VCF format, 229* and a collection of command-line utilities for executing complex manipulations on VCF files. 230 231The API itself provides a quick and extremely permissive method to 232read and write VCF files. Extensions and applications of the library 233provided in the included utilities (*.cpp) comprise the vast bulk of 234the library's utility for most users. 235 236<!-- 237 Created with ./scripts/bin2md.rb --index 238--> 239 240HEADER 241 TYPES.each do | type | 242 f.print %{ 243## #{type} 244 245| #{type} command | description | 246| :-------------- | :---------- | 247} 248 249 index.each do | rec | 250 rec = OpenStruct.new(rec) 251 if rec.type == type 252 b = binding 253 f.print renderer.result(b) 254 end 255 end 256 end 257 github = "https://github.com/vcflib/vcflib" 258 f.print <<FOOTER 259 260# SOURCE CODE 261 262See the source code repository at #{github} 263 264# LICENSE 265 266Copyright 2011-#{year} (C) Erik Garrison and vcflib contributors. MIT licensed. 267 268FOOTER 269 } 270end 271