Instantly share code, notes, and snippets.
-
Save mooffie/7aa12b593e84f729ff07 to your computer and use it in GitHub Desktop.
Permanent URLs for htags
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/ruby | |
# | |
# Fixes htags' output so that files have fixed names. E.g., S/542.html -> D/whatever.c.h. | |
# | |
# It addresses the following problem: | |
# | |
# "Can htags create permanent addresses?" | |
# http://lists.gnu.org/archive/html/help-global/2015-11/msg00002.html | |
# | |
require 'fileutils' | |
require 'pp' | |
Encoding.default_external = "BINARY" | |
$base = '.' # Where the HTML is stored. | |
$verbose = false | |
$debug = false | |
$create_subdirs = false # Experimental feature. Doesn't really work. | |
# Bonus: highlight the target line. | |
$css = " | |
a:target { | |
position: absolute; | |
left: 0; | |
height: 1.35em; | |
width: 100%; | |
background: yellow; | |
opacity: .5; | |
z-index: -1000; | |
} | |
" | |
# | |
# Computes pretty names for files: | |
# | |
# '.../S/456.html' => 'S/modules/tty.c.html' | |
# | |
def prettyname(full_path, prefix, kind, nid, ext) | |
gist = nid | |
start = IO.read(full_path, 1024) | |
if start =~ /<title>(.*?)<\/title>/ then | |
gist = $1 | |
gist.gsub!(%r{/+$}, '') # remove trailing '/'s. | |
if not $create_subdirs then | |
gist.gsub!('/', '--') | |
end | |
gist.gsub!(%r{[^a-zA-Z0-9_.,/-]}, '-') # clean special characters. | |
end | |
return kind + '/' + gist + ext | |
end | |
class Counter | |
class << self | |
def init(total) | |
@total = total | |
end | |
def reset() | |
@count = 0 | |
end | |
def report() | |
print "[#{@count}/#{@total}]\r" | |
@count += 1 | |
end | |
def finish() | |
puts | |
end | |
end | |
end | |
# | |
# Returns a table explaining how to rename the files. E.g.: | |
# | |
# { | |
# 'S/456.html' => 'S/modules/tty.c.html' | |
# ... | |
# } | |
# | |
def build_cnv_tbl() | |
Counter.reset() | |
cnv = {} | |
Dir[$base + '/{[A-Z],files}/*.html'].each do |full_path| | |
#p full_path | |
if full_path =~ /(.*)\/((\w+)\/(\d+)(\.\w+))$/ then | |
prefix = $1 # "/home/joe/.../HTML" | |
path = $2 # "S/323.html" | |
kind = $3 # "S" | |
nid = $4 # "323" | |
ext = $5 # ".html" | |
pretty = prettyname(full_path, prefix, kind, nid, ext) | |
cnv[path] = pretty | |
end | |
Counter.report() | |
end | |
Counter.finish() | |
return cnv | |
end | |
# | |
# Make all the substiutions inside the files: | |
# | |
# <a href='../S/456.html'> --> <a href='../S/modules/tty.c.html'> | |
# ... | |
# | |
def mksub(cnv) | |
Counter.reset() | |
Dir[$base + '/**/*.html'].each do |path| | |
kind = path[$base.length .. -1][/\w+/] | |
text = IO.read(path) | |
fixed = text.gsub(/(<a href='(?:..\/)?)([^'#]+)/) do |a| | |
prefix = $1 | |
target = $2 | |
if cnv[target] then | |
target = cnv[target] | |
elsif cnv[kind + '/' + target] then | |
# This is a relative link of the form: href='456.html' | |
if cnv[kind + '/' + target].match /\/(.*)/ # converts "s/whatever.html" to "whatever.html" | |
target = $1 | |
end | |
end | |
prefix + target | |
end | |
# Fix a problem in Opera, where empty lines are squashed. | |
fixed.gsub!(%r{(<a id='L\d+' name='L\d+'></a>)\n}, "\\1 \n") | |
if text != fixed then | |
IO.write(path, fixed) | |
puts(path + " modified") if $debug | |
end | |
Counter.report() | |
end | |
Counter.finish() | |
end | |
# | |
# Rename the files. | |
# | |
def rename(cnv) | |
Counter.reset() | |
cnv.each do |a, b| | |
src = $base + '/' + a | |
trg = $base + '/' + b | |
if $create_subdirs then | |
FileUtils.mkdir_p(File.dirname(trg)) | |
end | |
File.rename(src, trg) | |
Counter.report() | |
end | |
Counter.finish() | |
end | |
def better_css(css_path) | |
text = IO.read(css_path) | |
IO.write(css_path, text + $css) | |
end | |
def main() | |
if not File.exists?($base + '/help.html') then | |
$base += '/HTML' | |
if not File.exists?($base + '/help.html') then | |
puts "Error: This doesn't look like htags' output directory." | |
exit(1) | |
end | |
end | |
Counter.init( Dir[$base + '/**/*.html'].length ) | |
puts "Figuring out pretty names..." | |
cnv = build_cnv_tbl() | |
pp cnv if $verbose | |
puts "Updating links in files..." | |
mksub(cnv) | |
puts "Renaming files..." | |
rename(cnv) | |
puts "Enhancing the css..." | |
better_css($base + '/style.css') | |
puts "Done." | |
end | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment