For an Arduino LED animation project I have been working on an editor tool using HTML and javascript. After setting up various things, the tool enables generating C++ code to paste into an Arduino sketch.
It's all been working fine, the generated code compiles and runs on the board but there is an annoying 'auto-formatting' quirk in the Arduino IDE.
The code generator outputs a block of code like this:
const Scene scene_library[] PROGMEM = { { 7, 1, 40, 5, 320, 0xFF, { { 0, ANIM_ROW_CHASE, 1, 3, 0, 0, 0, 0 }, { 1, ANIM_ROW_CHASE, 2, 3, 0, 0, 0, 0 }, { 2, ANIM_ROW_CHASE, 3, 3, 0, 0, 0, 0 }, { 3, ANIM_ROW_CHASE, 4, 3, 0, 0, 0, 0 }, { 4, ANIM_ROW_CHASE, 5, 3, 0, 0, 0, 0 }, { 5, ANIM_ROW_CHASE, 6, 3, 0, 0, 0, 0 }, { 6, ANIM_ROW_CHASE, 7, 3, 0, 0, 0, 0 } }, 7 }};But if I use the 'auto-formatting' feature (cmd-T on MacOS) it unwraps the data and puts it on a single line. It still compiles and runs but it means the page scrolls horizontally a ridiculous amount.
What causes this and what I can do this fix it?
const Scene scene_library[] PROGMEM = { { 7, 1, 40, 5, 320, 0xFF, { { 0, ANIM_ROW_CHASE, 1, 3, 0, 0, 0, 0 }, { 1, ANIM_ROW_CHASE, 2, 3, 0, 0, 0, 0 }, { 2, ANIM_ROW_CHASE, 3, 3, 0, 0, 0, 0 }, { 3, ANIM_ROW_CHASE, 4, 3, 0, 0, 0, 0 }, { 4, ANIM_ROW_CHASE, 5, 3, 0, 0, 0, 0 }, { 5, ANIM_ROW_CHASE, 6, 3, 0, 0, 0, 0 }, { 6, ANIM_ROW_CHASE, 7, 3, 0, 0, 0, 0 } }, 7 }};I generate other data blocks which format fine:
const AnimConfig ambient_configs[] PROGMEM = { { 7, ANIM_STATIC_ROW, 0, 40, 0, 0, 255, 0 }, { 7, ANIM_STATIC_ROW, 0, 25, 0, 0, 255, 0 }, { 7, ANIM_STATIC_ROW, 0, 15, 0, 0, 255, 0 }, { 7, ANIM_STATIC_ROW, 0, 8, 0, 0, 255, 0 }, { 7, ANIM_STATIC_ROW, 0, 5, 8, 0, 255, 0 }};- upvote ... this is a really good subjectjsotola– jsotola2025-10-31 14:12:21 +00:00CommentedOct 31 at 14:12
- You can split the data into a separate array.user31256271– user312562712025-11-08 15:22:14 +00:00CommentedNov 8 at 15:22
1 Answer1
Fix
You can create a file named.clang-format in your sketch directory with the following content and the problem should go away. These are derived from IDE v2.3.6. For future versions it may be better to use original sources mentioned below.
AccessModifierOffset: -2AlignAfterOpenBracket: AlignAlignArrayOfStructures: NoneAlignConsecutiveAssignments: NoneAlignConsecutiveBitFields: NoneAlignConsecutiveDeclarations: NoneAlignConsecutiveMacros: NoneAlignEscapedNewlines: DontAlignAlignOperands: AlignAlignTrailingComments: trueAllowAllArgumentsOnNextLine: trueAllowAllConstructorInitializersOnNextLine: trueAllowAllParametersOfDeclarationOnNextLine: trueAllowShortBlocksOnASingleLine: AlwaysAllowShortCaseLabelsOnASingleLine: trueAllowShortEnumsOnASingleLine: trueAllowShortFunctionsOnASingleLine: EmptyAllowShortIfStatementsOnASingleLine: AllIfsAndElseAllowShortLambdasOnASingleLine: EmptyAllowShortLoopsOnASingleLine: trueAlwaysBreakAfterDefinitionReturnType: NoneAlwaysBreakAfterReturnType: NoneAlwaysBreakBeforeMultilineStrings: falseAlwaysBreakTemplateDeclarations: NoAttributeMacros:- __capabilityBasedOnStyle: LLVMBinPackArguments: trueBinPackParameters: trueBitFieldColonSpacing: BothBraceWrapping: AfterCaseLabel: false AfterClass: false AfterControlStatement: Never AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false BeforeLambdaBody: false BeforeWhile: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: trueBreakAfterJavaFieldAnnotations: falseBreakBeforeBinaryOperators: NonAssignmentBreakBeforeBraces: AttachBreakBeforeConceptDeclarations: falseBreakBeforeInheritanceComma: falseBreakBeforeTernaryOperators: trueBreakConstructorInitializers: BeforeColonBreakConstructorInitializersBeforeComma: falseBreakInheritanceList: BeforeColonBreakStringLiterals: falseColumnLimit: 80 #<---------------CommentPragmas: ''CompactNamespaces: falseConstructorInitializerAllOnOneLineOrOnePerLine: falseConstructorInitializerIndentWidth: 2ContinuationIndentWidth: 2Cpp11BracedListStyle: false#BreakAfterOpenBracketBracedList: trueDeriveLineEnding: trueDerivePointerAlignment: trueDisableFormat: falseEmptyLineAfterAccessModifier: LeaveEmptyLineBeforeAccessModifier: LeaveExperimentalAutoDetectBinPacking: falseFixNamespaceComments: falseForEachMacros:- foreach- Q_FOREACH- BOOST_FOREACHIfMacros:- KJ_IF_MAYBEIncludeBlocks: PreserveIncludeCategories:- Regex: ^"(llvm|llvm-c|clang|clang-c)/ Priority: 2 SortPriority: 0 CaseSensitive: false- Regex: ^(<|"(gtest|gmock|isl|json)/) Priority: 3 SortPriority: 0 CaseSensitive: false- Regex: .* Priority: 1 SortPriority: 0 CaseSensitive: falseIncludeIsMainRegex: ''IncludeIsMainSourceRegex: ''IndentAccessModifiers: falseIndentCaseBlocks: trueIndentCaseLabels: trueIndentExternBlock: IndentIndentGotoLabels: falseIndentPPDirectives: NoneIndentRequires: trueIndentWidth: 2IndentWrappedFunctionNames: falseInsertTrailingCommas: NoneJavaScriptQuotes: LeaveJavaScriptWrapImports: trueKeepEmptyLinesAtTheStartOfBlocks: trueLambdaBodyIndentation: SignatureLanguage: CppMacroBlockBegin: ''MacroBlockEnd: ''MaxEmptyLinesToKeep: 100000NamespaceIndentation: NoneObjCBinPackProtocolList: AutoObjCBlockIndentWidth: 2ObjCBreakBeforeNestedBlockParam: trueObjCSpaceAfterProperty: falseObjCSpaceBeforeProtocolList: truePPIndentWidth: -1PackConstructorInitializers: BinPackPenaltyBreakAssignment: 1PenaltyBreakBeforeFirstCallParameter: 1PenaltyBreakComment: 1PenaltyBreakFirstLessLess: 1PenaltyBreakOpenParenthesis: 1PenaltyBreakString: 1PenaltyBreakTemplateDeclaration: 1PenaltyExcessCharacter: 1PenaltyIndentedWhitespace: 1PenaltyReturnTypeOnItsOwnLine: 1PointerAlignment: RightQualifierAlignment: LeaveReferenceAlignment: PointerReflowComments: falseRemoveBracesLLVM: falseSeparateDefinitionBlocks: LeaveShortNamespaceLines: 0SortIncludes: NeverSortJavaStaticImport: BeforeSortUsingDeclarations: falseSpaceAfterCStyleCast: falseSpaceAfterLogicalNot: falseSpaceAfterTemplateKeyword: falseSpaceAroundPointerQualifiers: DefaultSpaceBeforeAssignmentOperators: trueSpaceBeforeCaseColon: falseSpaceBeforeCpp11BracedList: falseSpaceBeforeCtorInitializerColon: trueSpaceBeforeInheritanceColon: trueSpaceBeforeParens: ControlStatementsSpaceBeforeParensOptions: AfterControlStatements: true AfterForeachMacros: true AfterFunctionDefinitionName: false AfterFunctionDeclarationName: false AfterIfMacros: true AfterOverloadedOperator: false BeforeNonEmptyParentheses: falseSpaceBeforeRangeBasedForLoopColon: trueSpaceBeforeSquareBrackets: falseSpaceInEmptyBlock: falseSpaceInEmptyParentheses: falseSpacesBeforeTrailingComments: 2SpacesInAngles: LeaveSpacesInCStyleCastParentheses: falseSpacesInConditionalStatement: falseSpacesInContainerLiterals: falseSpacesInLineCommentPrefix: Minimum: 0 Maximum: -1SpacesInParentheses: falseSpacesInSquareBrackets: falseStandard: AutoStatementAttributeLikeMacros:- Q_EMITStatementMacros:- Q_UNUSED- QT_REQUIRE_VERSIONTabWidth: 2UseCRLF: falseUseTab: NeverWhitespaceSensitiveMacros:- STRINGIZE- PP_STRINGIZE- BOOST_PP_STRINGIZE- NS_SWIFT_NAME- CF_SWIFT_NAMEThe above is based options from the arduino-ide source repo.However,Edgar Bonet mentioned in a comment below:
Note that clang-format has decent default settings, which include ColumnLimit: 80. Thus, an empty style file is enough to avoid the overlong line. A style file with the single line PenaltyIndentedWhitespace: 1 would already give a decent formatting.
Cause
Bad default formatting options. Or at least ones not good for you.
I tend to just manually format things, so I'm not overly familiar with the formatting options.Theactive ingredient is this I noticed that broke formatting altogether in the IDE doing this, so I've temporarily changed the configuration to useBreakAfterOpenBracketBracedList: true.Initially I adjustedColumnLimit to at least clamp the code to the screen. I set that back to0 (no limit) whenBreakAfterOpenBracketBracedList seemed to do the job.ColumnLimit: 80.Apparently I was testing outside the IDE as well with a newer version of clang-format. If I find a better option, I'll update to that.
You may want to play around withthe other options to see if you can find a better way of going about it. Arduino IDE 2.3.6 bundlesclang-format version 14.0.0.
You don't need to reload the IDE or anything. You can modify that file and hitCTRL+T in the IDE until it does what you want, or at least until it does something you can stand. There do seem to exist web based tools for generating/editing clang format configurations that will give you a preview.
Sources
In you're wondering, what I'd done is look at IDE source code and foundthis comment:
* Calculates the `-style` flag for the formatter. Uses a `.clang-format` file if exists. * Otherwise, falls back to the default config. * * Style precedence: * 1. in the sketch folder, * 1. `~/.arduinoIDE/.clang-format`, * 1. `directories#data/.clang-format`, and * 1. default style flag as a string.You can see below that in the case that no custom.clang-format file is found itproduces a style based onthis file modifying itsTabWidth andUseTab setting with whatever were in the IDE preferences.
All I did was convert that file to yaml, and add theBreakAfterOpenBracketBracedListColumnLimit: 80 to it.
- If you find a better configuration change before I update, you can put it in your own answer or let me know in a comment and I may incorporate it into this one.timemage– timemage2025-10-31 07:44:40 +00:00CommentedOct 31 at 7:44
- 3Good find! Note that clang-format has decent default settings, which include
ColumnLimit: 80. Thus, an empty style file is enough to avoid the overlong line. A style file with the single linePenaltyIndentedWhitespace: 1would already give a decent formatting.Edgar Bonet– Edgar Bonet2025-10-31 09:02:13 +00:00CommentedOct 31 at 9:02 - 2super useful answer ... upvote ... please add the filename in the first sentence of your answerjsotola– jsotola2025-10-31 14:18:08 +00:00CommentedOct 31 at 14:18
- @EdgarBonet I didn't even think to try an empty file. I haven't been back to try things, but I wanted to incorporate your information. Sorry if it looks a bit shoehorned into the answer, but I thought it would be better to get it in front of a reader sooner rather than later.timemage– timemage2025-10-31 17:46:35 +00:00CommentedOct 31 at 17:46
- @jsotola Good catch. I managed to leave the clang-format version number out also, somehow.timemage– timemage2025-10-31 17:47:52 +00:00CommentedOct 31 at 17:47
Explore related questions
See similar questions with these tags.