The answer for your specific example is there, but the general
question remains.
In very many years, in both theoretical and applied computer science,
I do not recall having to write a CS grammar as such.
Still, if I may give an advice, it should not be seen at all like
producing a CF grammar, were you must contrive the rules to get
everything in place and coordinated exactly right as it is produced.
CS grammars are a lot more algorithmic, and you can pretty much mimic a
Turing machine (working in finite space, proportional to input size,
which means Linear Bounded Automaton - LBA) in order to move things
around as needed. So it is much more a programming exercise.
You can pretty much generates the first ingredients to build one of
the words in the language, then move them around algorithmically. You
can use special symbols (possibly in various flavors corresponding to
finite state) to act as heads that you move around with appropriate
rules, do as to check what is to be done. And so on.
A good reading may be to look at the proof of equivalence between CSG
languages and LBA languages, i.e. the CS languages.
Remember that nearly all algorithms that we work with can be performed
by a LBA, hence correspond to a CSG definable language. That should
give you an idea of the available algorithmic power.
But a bit of imagination helps elegant solutions, as in the example
you gave.