#!/usr/bin/env ruby # # Goes through every file under this directory, # fixing it's `#include` statement. # # * Gets a file name by looking at the last # path component of a `#include` # * Searches for it under this directory tree # * If found, inserts it's new relative path # * If not, simply prints the output. # That might be the case when it finds, say, # `#include <vector>` or `#include <string.h>` # # NOTE: It modifies the original files, so make # sure to use a VCS (like Git or SVN) or # at least have a backup somewhere! # # NOTE: You MUST be on the root of the source code # directory, since all `#include`s will be # based on that. # For example, if you have "src/file.cpp" you # must be on "src". require 'tempfile' require 'fileutils' # START OF USER CONFIGURABLE STUFF # Will not even touch other files allowed_extensions = ['.cpp', '.hpp'] # Will put all the lines on this file # and then rename it to the original tmp_file_name = '/tmp/temporary_file' # END OF USER CONFIGURABLE STUFF begin # Matches any line like "#include <path/to/File.cpp>" regexp_include = /\#include\s+<(.+)>/ # List of all files under this directory tree all_files = Dir.glob('**/*') all_files.each do |file| next if File.directory? file next if not allowed_extensions.member? File.extname(file) tmp = File.new(tmp_file_name, 'w') File.readlines(file).each do |line| match = line.match regexp_include if match.nil? tmp << line next end included = match[1] new_included = "" all_files.each do |this_file| if File.basename(this_file) == File.basename(included) new_included = this_file break end end # Didn't found the new file if (new_included.empty?) puts "Couldn't find file '#{included}'" tmp << line else tmp << "#include <#{new_included}>\n" end end tmp.close FileUtils.mv(File.path(tmp), file) end end