-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Next cpp setup #4
base: main
Are you sure you want to change the base?
Conversation
The runner works like the following for the Codewars style challenge with max 3 files:
So in the actual implementation, the preprocessor to split the solution/preloaded will be in step 2, outside the container. For the marker, can't we use #ifndef SOLUTION_INCLUDED
#define SOLUTION_INCLUDED
// solution.h
#endif // SOLUTION_INCLUDED
// anything after is `solution.cpp`
|
We can, and it would be even better, with a small caveat that if we wanted to use a language-neutral
Not saving a header when is not there in the snippet would be indeed clearer. I saved it because I was trying to build on top of Unnamed's idea to let author choose if the sippet should be used as a header or as an implementation if they choose to not use markers. The idea works (see |
I think the following works: const splitSnippet = (code: string, name: string): [header: string, impl: string] => {
const lines = code.split(/(?<=\n)/); // Keep LF in each line
const marker = new RegExp(
`^\\s*#\\s*ifndef\\s+${name.toUpperCase()}_INCLUDED`
);
const start = lines.findIndex((line) => marker.test(line));
// No header file unless there's a start marker.
if (start === -1) return ["", code];
let counter = 1;
const end = lines.findIndex((line, i) => {
if (i > start) {
if (/^\s*#\s*endif\s*/.test(line)) return --counter === 0;
if (/^\s*#\s*if(?:n?def)?\s+/.test(line)) ++counter;
}
return false;
});
// Put everything in header unless there's a matching `#endif`.
// The error should make more sense that way.
return end === -1
? [code, ""]
: [lines.slice(0, end + 1).join(""), lines.slice(end + 1).join("")];
}; It's only Used like: const [solutionH, solutionCpp] = splitSnippet(solution, "solution");
const files = [
{path: "include/solution.h", contents: solutionH},
{path: "src/solution.cpp", contents: solutionCpp},
// ...
]; With this convention, if users want to solve locally, they can just use separate files and concatenate on Codewars without adding anything proprietary. |
Looking at the reference, there's a few more, but yes, these three begin a new nesting level.
I think the latter is not necessary. IIRC a preprocessor directive must follow its starting Important part is to make sure that both files, |
…a container instead
Attempt at making the reporter a bit less verbose
Very rudimentary prototype of a setup with snippets preprocessor.
Directory
snippets
contains snippets of a kata as received from user or read from database:solution.snippet
,test_solution.snippet
, andpreloaded.snippet
.Directory
preprocessor
contains source code of a homegrown preprocessorcwpp
.The snippet are preprocessed with
cwpp
in a following way:solution.snippet
is searched for a header marker//! CW_SOLUTION_H
and implementation marker//! CW_SOLUTION_CPP
.solution.snippet
gets copied to bothinclude/solution.h
andsrc/solution.cpp
,solution.snippet
gets copied toinclude/solution.h
and an emptysrc/solution.cpp
is created,solution.snippet
gets copied tosrc/solution.cpp
and an emptyinclude/solution.h
is created,solution.snippet
gets split into bothinclude/solution.h
andsrc/solution.cpp
in a way described with the markers.preloaded.snippet
.configure
andrun-tests
are called.see
distribute-snippets.sh
for invocation of the CW preprocessor. Userun-all.sh
to run all the steps: preprocessing, build, and tests.