From 0699c433cf06dcde5d743893b7ca424ec9c64a1d Mon Sep 17 00:00:00 2001
From: namark <namark@disroot.org>
Date: Mon, 24 Sep 2018 04:05:48 +0400
Subject: [PATCH] Initial version of allinclude.

---
 .gitignore         |  5 +++
 Makefile           | 65 +++++++++++++++++++++++++++++++
 README.md          |  6 +++
 allinclude.cpp     | 95 ++++++++++++++++++++++++++++++++++++++++++++++
 allinclude_sort.sh |  2 +
 5 files changed, 173 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Makefile
 create mode 100644 allinclude.cpp
 create mode 100644 allinclude_sort.sh

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a2bbc73
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+# output files 
+out/
+
+# temporary files
+temp/
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..45e9b48
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,65 @@
+
+override CPPFLAGS	+= --std=c++1z
+override CPPFLAGS	+= -MMD -MP
+override CPPFLAGS	+= -I./include
+override CPPFLAGS	+= $(shell cat .cxxflags 2> /dev/null | xargs)
+
+PREFIX	:= $(DESTDIR)/usr/local
+BINDIR	:= $(PREFIX)/bin
+
+SOURCES	:= $(shell echo *.cpp)
+SCRIPTS	:= $(shell find -name *.sh)
+TEMPDIR	:= temp
+DISTDIR := out
+OUT		:= $(SOURCES:%.cpp=$(DISTDIR)/%)
+TARGET	:= $(OUT:$(DISTDIR)/%=$(BINDIR)/%)
+TARGET	+= $(SCRIPTS:%.sh=$(BINDIR)/%)
+OBJECTS	:= $(SOURCES:%.cpp=$(TEMPDIR)/%.o)
+DEPENDS	:= $(OBJECTS:.o=.d)
+
+build: $(OUT)
+
+$(DISTDIR)/%: $(TEMPDIR)/%.o | $(DISTDIR)
+	$(CXX) $(LDFLAGS) $< $(LDLIBS) -o $@
+
+$(TEMPDIR)/%.o: %.cpp | $(TEMPDIR)
+	$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<
+
+$(TEMPDIR):
+	@mkdir $@
+
+$(DISTDIR):
+	@mkdir $@
+
+clean:
+	@rm $(DEPENDS) 2> /dev/null || true
+	@rm $(OBJECTS) 2> /dev/null || true
+	@rmdir $(TEMPDIR) 2> /dev/null || true
+	@echo Temporaries cleaned!
+
+distclean: clean
+	@rm $(OUT) 2> /dev/null || true
+	@rmdir $(DISTDIR) 2> /dev/null || true
+	@echo All clean!
+
+install: $(TARGET)
+	@echo Install complete!
+
+$(BINDIR)/%: $(DISTDIR)/% | $(BINDIR)
+	install --strip $< $@
+
+$(BINDIR)/%: ./%.sh | $(BINDIR)
+	install $< $@
+
+$(BINDIR):
+	@mkdir $@
+
+uninstall:
+	-rm $(TARGET)
+	@rmdir $(BINDIR) 2> /dev/null || true
+	@echo Uninstall complete!
+
+-include $(DEPENDS)
+
+.PRECIOUS : $(OBJECTS)
+.PHONY : clean distclean uninstall
diff --git a/README.md b/README.md
index 8af5006..55d03b0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,8 @@
 # cpp_tools
+Here I collect tools I wrote for managing my c++ projects.
 
+### allinclude.cpp
+For each subdirectory in provided(or current) directory generates an .hpp file with the same name that includes all .h[pp] files in that subdirectory, then does the same recursively for each of those subdirectiry.
+
+### allinclude_sort.sh
+Wrapper for allinclude, that just uses sort command to sort the includes in generated hpp files.
diff --git a/allinclude.cpp b/allinclude.cpp
new file mode 100644
index 0000000..e5ab3ca
--- /dev/null
+++ b/allinclude.cpp
@@ -0,0 +1,95 @@
+#include <iostream>
+#include <string>
+#include <filesystem>
+#include <exception>
+
+#include "simple/file.hpp"
+
+namespace fs = std::filesystem;
+using namespace simple::file;
+
+void generate_allinclude(fs::path directory)
+{
+	std::cout << "generating allinclude files under: " << directory << '\n';
+	auto i = fs::directory_iterator(directory);
+	std::vector<fs::directory_entry> next_targets;
+	for(auto&& subdir : i)
+		if(subdir.is_directory())
+		{
+			std::cout << "for subdirectory: " << subdir << '\n';
+			auto inc_file_path = fs::path(subdir.path()).replace_extension(".hpp").native();
+			std::cout << "creating: " << inc_file_path << '\n';
+			auto include_file = wopex(inc_file_path);
+			auto i = fs::directory_iterator(subdir);
+			for(auto&& entry : i)
+			{
+				fs::path include;
+				if(entry.is_directory())
+				{
+					include = fs::path(entry.path()).replace_extension(".hpp");
+				}
+				else if(entry.path().extension() == ".hpp" || entry.path().extension() == ".h")
+				{
+					include = entry.path();
+				}
+
+				if(!include.empty())
+				{
+					auto relative = fs::relative(include, directory);
+					std::cout << "including: " << entry << " as " << relative << '\n';
+					include_file << "#include \"" << relative.native() << "\"\n";
+				}
+			}
+			next_targets.push_back(subdir);
+		}
+
+	for(auto&& target : next_targets)
+		generate_allinclude(target);
+}
+
+void clear_allinclude(fs::path directory)
+{
+	std::cout << "clearing existing allinclude files under: " << directory << '\n';
+	auto i = fs::directory_iterator(directory);
+	std::vector<fs::directory_entry> next_targets;
+	for(auto&& subdir : i)
+		if(subdir.is_directory())
+		{
+			next_targets.push_back(subdir);
+		}
+
+	for(auto&& subdir : next_targets)
+	{
+		std::cout << "for subdirectory: " << subdir << '\n';
+		auto inc_file_path = fs::path(subdir.path()).replace_extension(".hpp");
+		if(fs::remove(inc_file_path))
+			std::cout << "removed: " << inc_file_path << '\n';
+	}
+
+	for(auto&& target : next_targets)
+		clear_allinclude(target);
+}
+
+int main(int argc, char const* argv[]) try
+{
+	fs::path target = fs::current_path();
+	if(argc > 1)
+		target = argv[1];
+
+	if(!fs::is_directory(target))
+	{
+		std::cerr << "Specified path is not a directory!" << '\n';
+		return -1;
+	}
+
+	clear_allinclude(target);
+	std::cout << '\n';
+	generate_allinclude(target);
+}
+catch(const std::exception& ex)
+{
+	if(errno)
+		std::perror("Error: ");
+
+	std::cerr << "Exception: " << ex.what() << '\n';
+}
diff --git a/allinclude_sort.sh b/allinclude_sort.sh
new file mode 100644
index 0000000..eb05a69
--- /dev/null
+++ b/allinclude_sort.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+allinclude $1 | grep creating | sed 's/creating: //' | xargs -I{} sort -o {} {}
-- 
GitLab