<commit_before>#What Is This?
This is a script for bundling small C++ projects into a single to upload to CodinGame by resolving includes, include guards, and accompanying .cpp files
It's written in Python3, and only designed to cope
#How Do I Use It?
Usage is simple. Assuming you've got python3 installed correctly, just run the script (located at src/bundler.py in this repo) in python3, supplying a path to the source file containing your main method, and a path to the file you want the bundled code to be saved into as command line arguments.
I.e.:
    ```
        python3 bundler.py <main_file> <output_file>
    ```
E.g.:
    ```
        python3 bundler.py main.cpp bundled_code.cpp
    ```

If you omit the second argument, it will print the bundled code to standard output.

If you omit both arguments, it will attempt to look for a 'main.cpp' file in the current directory, and, if found, will use that as the input file.

#What Isn't It?
This script is NOT a full C++ macro preprocessor. As such, there are some caveats:
- `#define`, `#undefine`, `#ifdef`, and `#ifndef` macros that start with `__INCLUDE_GUARD_` (e.g. `#indef __INCLUDE_GUARD_MY_FILE`) will be omitted from the bundled code (after being processed)
- All code between an if macro meeting the criteria in the first point and the matching end-if macro, including the opening if, and that end-if will also be omitted (this is a feature)
- `#pragma once` macros are also removed (but will have been processed)
- All other macros are not processed, and are included as-is (if block nesting is safely tracked, though) - This means that, for example, `#define MY_FILE`, or `#if defined MY_FILE` would not be noticed

#What Does It Actually /Do/, Though?
As a rough summary, it:
- Processes local `#include`s (the ones using quotes, not angle-brackets)
- Auto detects header-source pairs, including the implementation code at the end of the relevant header file in the bundle output
- Supports `#pragma once`
- Processes include-guards and omits their contents when they are false. (but only those prefixed with `__INCLUDE_GUARD_`, at the moment)
- Auto-trims leading and trailing whitespace when taking from a file (thus omitting files whose contents are made empty by include guards entirely)
- Can import targets within directory paths (in both parent and child directories)
- Handles both `#ifdef` and `#ifndef` for include guards
- Ignores and reprints other preprocessor macros (including `#if`)
- Deals with nested ifs (even those it otherwise ignores)
- Can detect both .c and .cpp source files
- Auto-includes a line separator in case you don't. This line separator will be '\n' since the CG servers linux

Additionally, I've included a collection of small C++ files I used to test the script into the repo to give a concrete example of how the script behaves. They can be found in the tests directory. (and the output can be found at tests/out/bundled_code.cpp)

#TODO
This is a tentative to-do list of additional features I've considered, but have not yet implemented.
It is not intended to be a complete list. For a more concrete idea of future plans, see the issues section.
- Support for more complex/POSIX style command line arguments via parseargs
- Code minificiation (with varying levels of intensity)
- Support for specifying a custom include-guard prefix via cli arguments (even an empty '', if you wish)
- A cli flag for automatically pragma-oncing all headers, even if the macro is missing
- A cli flag for including `#pragma` optimisation macros at the top of the bundled code 
- Optionally performing some preprocessing optimisation within the script to squeeze out more performance (such as techniques described [here](https://www.codingame.com/forum/t/c-and-the-o3-compilation-flag/1670))

I'll implement these on an as-needed basis for my own use, or possibly if there are community requests for them.
Feel free to request additional features or report problems via the issues section of the repo. (or even implement changes yourself - pull-requests are welcome!)
<commit_msg>Updated the readme a little<commit_after>#What Is This?
This is a script for bundling small C++ projects into a single to upload to CodinGame by resolving includes, include guards, and accompanying .cpp files

It's written in Python3, and only designed to cope
#How Do I Use It?
Usage is simple. Assuming you've got python3 installed correctly, just run the script (located at src/bundler.py in this repo) in python3, supplying a path to the source file containing your main method, and a path to the file you want the bundled code to be saved into as command line arguments.
I.e.:
    ```
        python3 bundler.py <main_file> <output_file>
    ```
    
E.g.:
    ```
        python3 bundler.py main.cpp bundled_code.cpp
    ```

If you omit the second argument, it will print the bundled code to standard output.

If you omit both arguments, it will attempt to look for a 'main.cpp' file in the current directory, and, if found, will use that as the input file.

#What Isn't It?
This script is NOT a full C++ macro preprocessor. As such, there are some caveats:
- `#define`, `#undefine`, `#ifdef`, and `#ifndef` macros that start with `__INCLUDE_GUARD_` (e.g. `#indef __INCLUDE_GUARD_MY_FILE`) will be omitted from the bundled code (after being processed)
- All code between an if macro meeting the criteria in the first point and the matching end-if macro, including the opening if, and that end-if will also be omitted (this is a feature)
- `#pragma once` macros are also removed (but will have been processed)
- All other macros are not processed, and are included as-is (if block nesting is safely tracked, though) - This means that, for example, `#define MY_FILE`, or `#if defined MY_FILE` would not be noticed

#What Does It Actually Do, Though?
As a rough summary, it:
- Processes local `#include`s (the ones using quotes, not angle-brackets)
- Auto detects header-source pairs, including the implementation code at the end of the relevant header file in the bundle output
- Supports `#pragma once`
- Processes include-guards and omits their contents when they are false. (but only those prefixed with `__INCLUDE_GUARD_`, at the moment)
- Auto-trims leading and trailing whitespace when taking from a file (thus omitting files whose contents are made empty by include guards entirely)
- Can import targets within directory paths (in both parent and child directories)
- Handles both `#ifdef` and `#ifndef` for include guards
- Ignores and reprints other preprocessor macros (including `#if`)
- Deals with nested ifs (even those it otherwise ignores)
- Can detect both .c and .cpp source files
- Auto-includes a line separator in case you don't. This line separator will be '\n' since the CG servers linux

Additionally, I've included a collection of small C++ files I used to test the script into the repo to give a concrete example of how the script behaves. They can be found in the tests directory. (and the output can be found at tests/out/bundled_code.cpp)

#TODO
This is a tentative to-do list of additional features I've considered, but have not yet implemented.

It is not intended to be a complete list. For a more concrete idea of future plans, see the issues section.
- Support for more complex/POSIX style command line arguments via parseargs
- Code minificiation (with varying levels of intensity)
- Support for specifying a custom include-guard prefix via cli arguments (even an empty '', if you wish)
- A cli flag for automatically pragma-oncing all headers, even if the macro is missing
- A cli flag for including `#pragma` optimisation macros at the top of the bundled code 
- Optionally performing some preprocessing optimisation within the script to squeeze out more performance (such as techniques described [here](https://www.codingame.com/forum/t/c-and-the-o3-compilation-flag/1670))

I'll implement these on an as-needed basis for my own use, or possibly if there are community requests for them.

Feel free to request additional features or report problems via the issues section of the repo. (or even implement changes yourself - pull-requests are welcome!)
{'fraction_non_alphanumeric': 0.062461726883037354, 'fraction_numerical': 0.002449479485609308, 'mean_word_length': 4.26159793814433, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7333666', 'n_tokens_mistral': 2183, 'n_tokens_neox': 2068, 'n_words': 1238}