Created
December 10, 2015 08:00
-
-
Save JensAyton/f7a2bb8b259d008933cb to your computer and use it in GitHub Desktop.
Macro for pasting ANSI escape codes together, based on https://twitter.com/velartrill/status/674797360774569984. This version requires GCC/Clang extensions for handling zero-length macro __VA_ARGS__es, because I’m lazy, but it could be done without. Note that this is an awful idea because sooner or later you’ll want to output to a text file and …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef format_h | |
#define format_h | |
#define reset "0" | |
#define bold "1" | |
#define red "31" | |
#define format(first, ...) \ | |
"\e[" first join_format_codes(__VA_ARGS__) "m" | |
#define prepend_joiner(s) \ | |
";" s | |
#define join_format_codes(...) \ | |
JATEMPLATE_MAP(prepend_joiner, __VA_ARGS__) | |
// Stuff I happened to have lying around follows. | |
#define JATEMPLATE_ARGUMENT_COUNT(...) \ | |
JATEMPLATE_ARGUMENT_COUNT_INNER(_0, ##__VA_ARGS__, JATEMPLATE_ARGUMENT_COUNT_63_VALUES()) | |
#define JATEMPLATE_ARGUMENT_COUNT_INNER(...) \ | |
JATEMPLATE_ARGUMENT_COUNT_EXTRACT_64TH_ARG(__VA_ARGS__) | |
#define JATEMPLATE_ARGUMENT_COUNT_EXTRACT_64TH_ARG( \ | |
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ | |
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ | |
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ | |
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ | |
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ | |
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ | |
_61,_62,_63,N,...) N | |
#define JATEMPLATE_ARGUMENT_COUNT_63_VALUES() \ | |
62,61,60, \ | |
59,58,57,56,55,54,53,52,51,50, \ | |
49,48,47,46,45,44,43,42,41,40, \ | |
39,38,37,36,35,34,33,32,31,30, \ | |
29,28,27,26,25,24,23,22,21,20, \ | |
19,18,17,16,15,14,13,12,11,10, \ | |
9,8,7,6,5,4,3,2,1,0 | |
#define JATEMPLATE_MAP(F, ...) \ | |
JATEMPLATE_MAP_INNER(F, JATEMPLATE_ARGUMENT_COUNT(__VA_ARGS__), __VA_ARGS__) | |
#define JATEMPLATE_MAP_INNER(F, COUNTEXPR, ...) \ | |
JATEMPLATE_MAP_INNER2(F, COUNTEXPR, __VA_ARGS__) | |
#define JATEMPLATE_MAP_INNER2(F, COUNT, ...) \ | |
JATEMPLATE_MAP_INNER3(F, JATEMPLATE_MAP_IMPL_ ## COUNT, __VA_ARGS__) | |
#define JATEMPLATE_MAP_INNER3(F, IMPL, ...) \ | |
IMPL(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_0(F, HEAD) | |
#define JATEMPLATE_MAP_IMPL_1(F, HEAD) F(HEAD) | |
#define JATEMPLATE_MAP_IMPL_2(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_1(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_3(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_2(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_4(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_3(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_5(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_4(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_6(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_5(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_7(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_6(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_8(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_7(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_9(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_8(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_10(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_9(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_11(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_10(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_12(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_11(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_13(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_12(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_14(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_13(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_15(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_14(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_16(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_15(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_17(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_16(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_18(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_17(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_19(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_18(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_20(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_19(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_21(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_20(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_22(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_21(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_23(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_22(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_24(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_23(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_25(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_24(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_26(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_25(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_27(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_26(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_28(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_27(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_29(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_28(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_30(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_29(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_31(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_30(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_32(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_31(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_33(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_32(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_34(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_33(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_35(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_34(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_36(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_35(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_37(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_36(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_38(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_37(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_39(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_38(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_40(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_39(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_41(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_40(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_42(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_41(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_43(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_42(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_44(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_43(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_45(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_44(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_46(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_45(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_47(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_46(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_48(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_47(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_49(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_48(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_50(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_49(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_51(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_50(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_52(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_51(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_53(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_52(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_54(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_53(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_55(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_54(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_56(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_55(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_57(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_56(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_58(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_57(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_59(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_58(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_60(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_59(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_61(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_60(F, __VA_ARGS__) | |
#define JATEMPLATE_MAP_IMPL_62(F, HEAD, ...) F(HEAD), JATEMPLATE_MAP_IMPL_61(F, __VA_ARGS__) | |
#endif /* format_h */ |
Additional macro hack to reduce namespace pollution (the example works unmodified, bold
etc are valid only within format()
):
#define format_hack_reset "0"
#define format_hack_bold "1"
#define format_hack_red "31"
#define format(...) \
format_hack_format(JATEMPLATE_MAP(format_hack_prepend_namespace, __VA_ARGS__))
#define format_hack_format(...) \
format_hack_format_inner(__VA_ARGS__)
#define format_hack_format_inner(first, ...) \
"\e[" first format_hack_join_format_codes(__VA_ARGS__) "m"
#define format_hack_prepend_joiner(s) \
";" s
#define format_hack_join_format_codes(...) \
JATEMPLATE_MAP(format_hack_prepend_joiner, __VA_ARGS__)
#define format_hack_prepend_namespace(s) \
format_hack_##s
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage: