Gtk4-tutorial/lib/lib_sec_file.rb

158 lines
3.6 KiB
Ruby

class Sec_file < String
def initialize path
if path.instance_of?(String) && File.exist?(path)
@name = File.basename path
@dirname = File.dirname path
unless @name =~ /^sec\d+(\.\d+)?\.(src\.md|md|html|tex)$/
raise "Sec_file class initialization error: #{path} is not Sec_file object name."
end
super(path)
else
raise "Sec_file class initialization error: file #{path} is not exist."
end
end
def type
@name.match(/\.(src\.md|md|html|tex)$/)[1]
end
def path
self
end
def name
@name
end
def dirname
@dirname
end
def c_files
if self.type != "src.md"
return []
else
buf = IO.readlines(self)
files = []
buf.each do |line|
if line =~ /^@@@ (\S+)/
files << @dirname+"/"+$1
end
end
files
end
end
def to_srcmd
@name.gsub(/\.(src\.md|md|html|tex)$/, ".src.md")
end
def to_md
@name.gsub(/\.(src\.md|md|html|tex)$/, ".md")
end
def to_html
@name.gsub(/\.(src\.md|md|html|tex)$/, ".html")
end
def to_tex
@name.gsub(/\.(src\.md|md|html|tex)$/, ".tex")
end
def num # the return value is String
@name.match(/\d+(\.\d+)?/)[0]
end
def to_f
self.num.to_f
end
def <=> other
if other.instance_of?(Sec_file)
self.to_f <=> other.to_f
else
nil
end
end
# Note: is_i? indicates the number is integer mathematically. For example, 2.0 is an integer.
# It doesn't mean the class of the number is Integer.
def is_i?
self.to_f == self.to_f.floor
end
def renum! n
if n.instance_of?(String)
n = n.to_i if n =~ /^\d+$/
n = n.to_f if n =~ /^\d+\.\d+/
end
if n.instance_of?(Integer) || n.instance_of?(Float)
n = n.to_i if n == n.floor
old = self
new = self.gsub(/\d+(\.\d+)?(\.(src\.md|md|html|tex)$)/, "#{n}\\2")
if old != new
File.rename old, new
self.replace new
@name = File.basename self
@dirname = File.dirname self
end
end
end
end
class Sec_files < Array
def initialize sec_files
if sec_files.instance_of? Array
sec_files.each do |sec_file|
unless sec_file.instance_of? Sec_file
raise "#{sec_file} is not an instance of Sec_file."
end
end
super(sec_files)
else
raise "#{sec_files} is not an array."
end
end
def renum!
self.sort!
tbl = []
n = 1
self.each do |sec_file|
tbl << [ sec_file.num, n, sec_file.to_f == n ? true : false ]
n += 1
end
while any_diff?(tbl)
unless try_renum(tbl)
break
end
end
if any_diff?(tbl)
raise "Renumbering failed."
end
end
private
def any_diff? tbl
diff = false
tbl.each do |t|
diff = true if t[2] == false
end
diff
end
def try_renum tbl
changed = false
(self.size - 1).downto 0 do |i|
if tbl[i][2] == false
n = tbl[i][1] # number to substitute
found = false
self.each do |sec_file|
if sec_file != self[i] && sec_file.to_f == n
found = true
break
end
end
unless found # OK to replace
self[i].renum! n
tbl[i][2] = true
# tbl[0] (old number (String) is kept in the array 'tbl')
changed = true
self.each do |sec_file|
buf_n = []
buf = IO.readlines sec_file
buf.each do |line|
buf_n << line.gsub(/((S|s)ection *)#{tbl[i][0]}/, "\\1#{n}").gsub(/((S|s)ec *)#{tbl[i][0]}/, "\\1#{n}")
end
IO.write sec_file, buf_n.join
end
end
end
end
changed
end
end