Formatting by Language

How to indent C and C++ code on Mac

You can do this with Note My, and here is the single control that re-indents C and C++, and exactly what each option inside it does to braces, access labels and namespace bodies.

A C or C++ file goes ragged in ordinary ways. A pasted block arrives with three-space indent. A merge leaves a brace one level too deep and every line under it follows. Two statements end up sharing a line. public: sits with the members in one class and at the class's own margin in the next, and nobody remembers which was intended. None of it is a compile error, which is exactly why it survives.

This guide covers the one control in Note My that re-indents a C or C++ file, what each of its C and C++ options changes, and how to make a whole file agree in a single pass. Our indentation engine does the tidying so you do not have to go line by line, and it does it entirely on your Mac — no account, no upload, no source leaving the machine.

Where re-indentation lives

Re-indentation has one home: the Indent button in the toolbar, drawn as a pair of curly braces. It sits in plain sight on every window, in the same place in every document, so there is nothing to hunt for and nothing to memorise. Click it and every control this guide describes comes to you at once.

The button does not reformat anything on its own. It opens the Indentation sheet, a floating panel over your window, and your document is untouched until you press Apply. You can open the sheet, read every switch, change your mind and press Cancel with no consequence at all. That makes the sheet a safe place to explore.

Note

Indent does more than move whitespace. It also unpacks statements that share a line, so int a = 1; int b = 2; comes back as two lines. Expect that before you apply it to code you care about.

Re-indent a C or C++ file

  1. Open the file and check the language

    Our advanced language identifier names the language for you, so a file you have just opened is usually ready to format without any setup. Glance at the status bar to see what it is set to. If it is not what you want — a header you treat as C++, or a file with an unusual extension — the Identify pill opens the Language Inspector, where you can set the language yourself and confirm it. That choice sticks for the document, colouring included.

  2. Click Indent in the toolbar

    The Indentation sheet opens over the window. Nothing has changed in your document yet.

  3. Pick the language in the sheet

    The picker offers sixteen entries: a global default plus fifteen languages, with C and C++ listed separately. The sheet's own choice is the one that gets applied, so a header the status bar calls C can still be formatted as C++ by choosing it here. Changing the language snaps the brace style, width and tabs controls to the ones you last used for that language.

  4. Set the brace style and the width

    Two brace styles, a width between 1 and 12, and tabs or spaces. The preview card redraws as you change them.

  5. Work through the language-specific section

    Below the general controls is the section that only applies to C and C++: access labels, namespace bodies, case labels, preprocessor lines and pointer spacing. Each is covered in detail below.

  6. Press Apply

    The whole document is re-indented, top to bottom, and the sheet closes. Every class, every switch and every guarded block comes back agreeing with the settings you have just read. Press ⌘S before you open the sheet and the saved copy is always a keystroke away.

What the preview card shows you

The card in the middle of the sheet is a live preview: monospaced text with the braces tinted blue, redrawn with a short cross-fade whenever you change the width, the tab setting or the brace style. It is there to answer the question you have while you are setting the sheet up: what four spaces and Allman braces are actually going to look like in your own file.

The sample it draws is a compact if <condition> { … } block, rendered in exactly the width, the unit and the brace style you currently have selected. That makes it the quickest way to settle those three: nudge the width, flip the brace style, and read the result rather than imagining it. For the C and C++ conventions further down the sheet — access labels, namespace bodies, case labels — the switches themselves are the documentation, and each one is described in detail below.

Brace style: same line or next line

Two styles cover the way C and C++ is actually written. Same line is the K&R form and is the default:

cpp
class Session {
public:
    void open() {
        if (ready) {
            connect();
        }
    }
};

Next line is the Allman form:

cpp
class Session
{
public:
    void open()
    {
        if (ready)
        {
            connect();
        }
    }
};

Brace style is one of the three settings the sheet remembers per language, so you can keep C++ on Allman and JavaScript on the same line without them fighting each other.

The C and C++ options in detail

Four switches and one pop-up sit in the language-specific section. Every one of them changes something people argue about, which is presumably why they are switches.

The C and C++ specific indentation controls and what each one changes
ControlWhat it changes
Access-label outdentWhether public:, protected: and private: sit at the class's own margin or one level in, with the members.
Namespace-body indentWhether the contents of a namespace gain a level. On by default.
Case-label indentWhether case and default: sit one level inside the switch or level with it.
Preprocessor flushWhether #include, #define, #ifdef and the rest are pulled to the left margin regardless of the block they appear in.
Pointer and reference styleWhere the spaces go around * and & in a declarator. Five options.

Access labels

The outdent switch decides between these two shapes:

cpp
class Session {
public:
    void open();
private:
    int fd;
};

class Session {
    public:
        void open();
    private:
        int fd;
};

Neither is wrong; the point is that after Apply, every class in the file agrees. Set the switch to the shape your project uses and a header someone else started comes back looking like the rest of your code. Read the switch in the sheet before you apply it, so the shape you get is the shape you chose, and one pass carries it through a header holding three classes as readily as a source file holding one.

Namespace bodies

Indenting a namespace body is on by default, which is the shape most C++ code takes. Turn it off and the contents stay flush with the namespace keyword, which is the convention in projects that nest two or three deep and do not want to lose columns to it. One switch settles it for every namespace in the file, however deeply they nest.

Case labels

The case-label switch decides whether case lines sit one level inside their switch or level with it. The bodies under each label are indented either way; what moves is the label itself.

Preprocessor lines

Preprocessor flush pulls directives to column zero. It matters when an #ifdef guards a block halfway inside a function: with flush on, the #ifdef and its #endif go to the margin where they are easy to pair up by eye; with it off, they follow the code around them.

Pointer and reference declarators

Five options, and the default is to leave every declarator exactly as you wrote it:

The five pointer and reference spacing options
OptionResult
Preserve (default)Each declarator is left as written. Nothing is normalised.
Space on the leftint *p
Space on the rightint* p
Space on both sidesint * p
No spaceint*p
Important

Pointer style is one house rule covering C and C++ together. Set it while formatting a C++ file and your C files follow the same convention, which is usually exactly what you want in a codebase that mixes the two. The four switches above it work the same way, so a decision you make once carries to every C and C++ file you tidy afterwards. Decide it deliberately, and a project stops arguing with itself.

Indent width, tabs and spaces

The width defaults to 4 and the sheet accepts 1 to 12. Spaces are the default unit; the tabs switch changes that. Two languages carry a lock — Go to tabs, which is on out of the box, and Python to four spaces, which is off out of the box — and neither applies to C or C++, so both units are yours to choose here.

If you want to see the result rather than trust it, two toolbar toggles help. Show Invisibles draws spaces, tabs and line endings so you can see which unit is actually in the file, and Guides draws indentation guides down each level. Guides come in ten styles, chosen in Settings ▸ Guides, with dots as the default.

What gets remembered per language

Three settings follow the language you choose: brace style, indent width and tabs versus spaces. That is what lets C++ sit on Allman at four spaces while JavaScript keeps its braces on the same line at two, each remembered and reapplied the next time you open the sheet on that kind of file. The remaining controls — access labels, namespaces, case labels, preprocessor flush, pointer style — are house style, applied wherever you format.

The sheet makes that split visible in its own Reset to global link, which appears when the selected language is carrying overrides. It returns those three settings to your global default and leaves your house style exactly where you put it, so a quick reset on one language never disturbs the conventions you have settled for everything else. Pointer style rides through a reset untouched, and the pop-up is where you change it whenever you want something different.

Recovering code a comment marker swallowed

The sheet has one more checkbox: Recover damaged comments, off by default. It exists for a specific accident — a line where // ended up in front of code that was meant to run, so a single line now reads as a comment followed by two statements. With it on, that line is split back apart and the code beneath it lines up again.

It is deliberately cautious rather than clever, and the rules it works to are worth knowing:

  • Single-line comments only. A block comment keeps its markers and stays a comment; it is tidied in place, never un-commented.
  • Anything ambiguous is left exactly as you wrote it. Nothing is un-commented on a hunch, so a note to yourself stays a note to yourself and what comes back to you is code that had been commented out.
  • Documentation markers — ///, //!, /** and /*! — are always skipped, so your doc comments are never touched.

The checkbox is built for C and C++, where a stray // does the most damage and hides the most work. Leave it off for a routine tidy-up and turn it on when you already suspect a line was commented out by accident — a bad merge, a stray keystroke, a block someone disabled and forgot on a Friday. Because it only ever hands code back to you, the worst it can do on a file that never had the problem is nothing at all.

Troubleshooting

I clicked Indent and nothing happened

The button opens the sheet; it never formats on its own. If the sheet opened and Apply appeared to do nothing, the file was probably already indented the way you asked for. An empty document gives it nothing to change, so nothing changes.

I want the file as it was before the re-indent

The dependable route back is the copy on disk, and it is one keystroke away. Press ⌘S before you open the sheet, and File ▸ Reload from Disk (⌘R) will bring that saved copy straight back into the window whenever you want to try different settings. Reloading never changes the file on disk, so you can go back and forth as often as you like while you decide on a brace style. After a whole-document format, reach for reload rather than undo. Make it a habit: ⌘S, then Indent.

One part of the file came back wrong

A re-indent follows the braces it is given, so an unbalanced brace — or a macro that opens a block without closing it — leaves everything below sitting one level too deep. That is useful information rather than a nuisance: the indentation has just drawn you a map of where the structure goes astray. Look for the first line that is wrong, not the worst-looking one; the mistake is usually just above it. Fix the brace, reload from disk, and run it again. If the offending brace is hard to spot by eye, turn on Guides and follow the level that never comes back to the margin.

Re-indenting a very large source file

A heavy file is re-indented exactly the way a short one is, and the moves are the ones you already know: you open the file, you open the sheet, you press Apply. A generated header of tens of thousands of lines goes through the same single pass as a fifty-line source file, and our large-file engine is built for exactly that kind of document. On a document that long Apply takes a visible moment before the whole thing comes back; give it that moment and the document arrives re-indented from the first line to the last, in one piece. While you are working in a document that size the status bar marks it as a large file — information, rather than anything you need to act on.

Typing a label gives me an extra level of indent

That is smart editing as you type, not the Indent button. Auto-indent on Return adds a level after a trailing {, [, ( — or a trailing colon, in every language. In C++ that shows up on public:, on case x: and on a goto label. Running Indent puts it right afterwards. The Return behaviour is one of five smart-editing switches, all on by default, reachable from the toolbar Smart Edit toggle and Settings ▸ Editing.

The file mixes tabs and spaces and the result still looks uneven

Re-indenting writes leading whitespace in the unit you chose, but a mixture elsewhere in the file is a separate problem. Mixed tab/space indent is one of the categories our hidden-character scanner covers, under Clean ▸ Clean Invisible / Special Characters…, where you can look through the document and see exactly which lines are affected before you change anything. Do that first, then re-indent.

What else a tidy C or C++ file lets you do

Re-indenting is usually the first move rather than the last. Once every brace sits at the level it belongs to and the access labels agree from the top of the file to the bottom, the rest of the work on that file gets quicker.

  • Fix the whole file in one pass. Apply works across the entire document, so a source file three people have touched at three different widths comes back consistent from the first #include to the last closing brace, plain functions and deeply nested templates alike, in a single move.
  • Settle the shape before you commit. The live preview redraws as you change the width, the unit and the brace style, so you can weigh Allman against K&R by looking at it rather than arguing about it, then read the C and C++ switches and press Apply once you are happy.
  • Hold two languages to one house style. Access labels, namespace bodies, case labels, preprocessor flush and pointer spacing carry across C and C++ together, so a codebase that mixes the two ends up reading as one project.
  • Keep your settings between sessions. Brace style, width and unit are remembered for each language, so the next C++ file you open is formatted the way you formatted the last one, with nothing to set up first.
  • See exactly what changed. Put the tidied file beside the version a colleague sent you in our comparison view and the real differences stand out, instead of every line reading as changed because the indentation moved.
  • Sweep a name through the file. With the code laid out predictably, our find and replace is the quick way to rename a symbol or retire an old macro, because the matches now sit where you can scan them rather than buried inside a run-on line.
  • Repeat an edit you have done once. If a generated header needs the same run of small changes every time a new one lands, our macro recorder can capture that sequence and play it back over the next file.
  • Fold what you are not reading. Double-click a brace and its block collapses, which turns a long implementation file into a list of functions you can move through quickly and expand only where you are working.
  • Keep your comments word for word. A routine re-indent moves whitespace and brace placement and leaves the text of your comments exactly as you wrote it. Licence headers, section banners and the note explaining why a magic number is what it is all survive the pass.

Frequently asked questions

How do I re-indent a whole file?

Click Indent in the toolbar, choose the language and the options you want in the sheet, and press Apply. That one pass covers the document top to bottom. The keyboard helps once the sheet is open: Return applies your settings and Escape closes the sheet with the document untouched.

Will it change my code as well as my whitespace?

In three specific ways, yes. It unpacks statements that share a line onto separate lines. The pointer-style pop-up, if you move it off Preserve, rewrites the spacing in declarators. And comment recovery, if you switch it on, splits a line where a comment marker swallowed code. Everything else is indentation and brace placement. Save before you apply.

Can I format a header as C++ when the app calls it C?

Yes. The sheet's language picker is what gets applied for that run, so choosing C++ there formats it as C++ regardless of what the status bar says. If you want the whole document treated as C++ from then on — colouring included — set it from the Identify pill in the status bar, which opens the Language Inspector, where you choose the language and confirm.

Does it use tabs or spaces by default?

Spaces, four of them. The sheet accepts any width from 1 to 12, and the tabs switch is right beside it. Both settings are remembered per language, so C++ and C can differ.

What does the preview card show?

A small if block, drawn in exactly the width, unit and brace style you have chosen and redrawn the moment you change any of the three. It is the fastest way to see what a width or a brace style will look like before you apply it to anything. For the C and C++ options, the switches themselves are the documentation.

Does any of this send my source anywhere?

Nothing leaves your Mac. Note My contains no networking code of its own; the only network activity is performed by Apple’s own system services, to establish purchases and transactions state. There is no telemetry, no update check and no account to sign into. Formatting happens on your Mac, and your source never leaves the machine.