Composing “partial writers”?
Apparently all roads lead back to this library! I am back after a couple of years 😅
I have a use case where I'm building properties in a class -- more specifically, for creating a mock API class based on swagger spec. I construct the arguments for each endpoint, the return type, the default mock object to return from the endpoint, and check for arguments name like “id” to provide special casing. The point is, there's a lot happening, and most of it is inline, writing to writer slowly after numerous checks and switch-cases.
What's happening now is that I realize that I need to write two very similar properties. (Don't ask -- our real API has methods like getUsers and getUsersRaw, where the ~Raw variant gives you more details on the response, like its headers, etc.)
As it currently is, I have to copy/paste the whole body of the loop iterating over endpoints, and then tweak a few things here and there.
But I realize it would be much better if I could write into two separate “partial writers”, and then “compose” them back into the main code. The greatest strength of this library for me is the way it handles indentation and common annoying things like conditionalNewLine. So the biggest issue in writing two random chunks of code, and then putting them inside another piece of code at an arbitrary position would be re-indenting the chunks to match.
If you have this main code--
class Foo {
bar (condition) {
if (condition) {
// (1)
} else {
// (2)
}
}
}
--and in two separate writers you have these two--
for (const x of [1, 2, 3]) {
console.log(x)
}
switch (x) {
case 'x':
console.log(x)
default:
console.log('?')
}
--then the problem of just "injecting" one into other is that you'd naturally get this--
class Foo {
bar (condition) {
if (condition) {
for (const x of [1, 2, 3]) {
console.log(x)
}
} else {
switch (x) {
case 'x':
console.log(x)
default:
console.log('?')
}
}
}
}
--which is not terrible for generated code, but if you do this a couple of times it becomes completely unreadable.
So I was wondering if you think this is something worth pursuing. It could be a method that would insert an arbitrary string, but parse it for new lines and adjust indentation. Of course, this could be problematic if the newline occurs in a template string in TypeScript for example, but this could either be a well-documented caveat (i.e. ALL new lines will be re-indented, as Writer doesn't know the syntax of the language you're printing). Another idea is to have a special PartialWriter, or modify the existing Writer, that would keep lines in memory instead of just the whole string, so printing those lines is possible with various "external" indentation settings.
I think the most similar feature that the library already has is the way quote already works: it parses the given string and tweaks what will actually be written. If we're hunting for " in a string to replace it with \", then it might not be such a terrible idea to have a way to hunt for \n and replace it with \n ?
...Or am I missing something obvious and this is already possible? 🥲