# Automatische Code Formatierung

**URL:** <https://forum.espuino.de/t/automatische-code-formatierung/1908>\
**Category:** Software\
**Created:** [11. April 2023 um 14:57 UTC](https://forum.espuino.de/t/automatische-code-formatierung/1908 "2023-04-11T14:57:37Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

**Author:** ![laszloh](https://forum.espuino.de/user_avatar/forum.espuino.de/laszloh/32/1975_2.png) [@laszloh](https://forum.espuino.de/u/laszloh)\
**Post date:** [11. April 2023 um 14:57 UTC](https://forum.espuino.de/t/automatische-code-formatierung/1908/1 "2023-04-11T14:57:37Z")

</div>

> Edit von @biologist am 05.11.2023:
> 
> - Wir haben uns final für clang-format entschieden.
> - Wie man das einrichtet ist [weiter unten](https://forum.espuino.de/t/automatische-code-formatierung/1908/65) beschrieben.

Hallo,  
Ich ziehe das Thema aus [Zugangsdaten mehrerer Wlans speichern](https://forum.espuino.de/t/zugangsdaten-mehrerer-wlans-speichern/1874) heraus. Hintergrund, ich habe einige Code Format Tools für VSCode (bzw für C und C++) angeschaut und wollte euch die mal vorstellen, bzw Inputs holen.  
Bei der Auswahl habe ich mich in erster Linie auf Tools gestürzt, die ich selbst kenne.

Diese Punkte wären ein automatisches No-Go für ein Tool:

1. Es muss von VSCode Native order per Plugin unterstützt sein, oder sich in Platformio / Github als Build integrieren lassen
2. Es muss Binaries / Sources für die gängisten Betriebsysteme geben (Windows, Mac: Binary, Linux: min. Source)
3. Die Konfiguration muss über ein Config-File im Projektordner erfolgen (können). Ohne dem müsste jeder alle Einstellungen manuell machen → No-Go
4. Die Config-File muss Text-Basiert sein, damit Git es erkennen und aufnehmen kann.

Als Tool für die Erstellung der Beispiele weiter unten habe ich [UniversalIndentGUI](https://sourceforge.net/projects/universalindent/) gefunden und damit herumgespielt gehabt.

  

# C-Code

> **Original Code der für alle Formatter verwendet wurde**
>
> ```cpp
> #include <Arduino.h>
> #include "settings.h"
> #include "Log.h"
> #include "Button.h"
> #include "Cmd.h"
> #include "Port.h"
> #include "System.h"
> 
> bool gButtonInitComplete = false;
> 
> // Only enable those buttons that are not disabled (99 or >115)
> // 0 -> 39: GPIOs
> // 100 -> 115: Port-expander
> #if (NEXT_BUTTON >= 0 && NEXT_BUTTON <= MAX_GPIO)
> #define BUTTON_0_ENABLE
> #elif (NEXT_BUTTON >= 100 && NEXT_BUTTON <= 115)
> #define EXPANDER_0_ENABLE
> #endif
> 
> class z {
> public:
> z() { }
> void doStuff(int z) { return l; }
> };
> 
> t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
> uint8_t gShutdownButton = 99; // Helper used for Neopixel: stores button-number of shutdown-button
> uint16_t gLongPressTime = 0;
> 
> #ifdef PORT_EXPANDER_ENABLE
> extern bool Port_AllowReadFromPortExpander;
> #endif
> 
> static volatile SemaphoreHandle_t Button_TimerSemaphore;
> 
> void Button_Init() {
> #if (WAKEUP_BUTTON >= 0 && WAKEUP_BUTTON <= MAX_GPIO)
> if (ESP_ERR_INVALID_ARG == esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKEUP_BUTTON, 0)) {
> snprintf(Log_Buffer, Log_BufferLength, "%s (GPIO: %u)", (char *) FPSTR(wrongWakeUpGpio), WAKEUP_BUTTON);
> Log_Println(Log_Buffer, LOGLEVEL_ERROR);
> }
> #endif
>     
> if (x) {
> y = z;
> }
> 
> switch (a) {
> case b:
> break;
> }
> 
> for (int i = 0; i < 5; i++) {
> i--;
> }
> 
> #ifdef NEOPIXEL_ENABLE // Try to find button that is used for shutdown via longpress-action (only necessary for Neopixel)
> #if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
> #if (BUTTON_0_LONG == CMD_SLEEPMODE)
> gShutdownButton = 0;
> #endif
> #endif
> #if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
> #if (BUTTON_1_LONG == CMD_SLEEPMODE)
> gShutdownButton = 1;
> #endif
> #endif
> #if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
> #if (BUTTON_2_LONG == CMD_SLEEPMODE)
> gShutdownButton = 2;
> #endif
> #endif
> #if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
> #if (BUTTON_3_LONG == CMD_SLEEPMODE)
> gShutdownButton = 3;
> #endif
> #endif
> #if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
> #if (BUTTON_4_LONG == CMD_SLEEPMODE)
> gShutdownButton = 4;
> #endif
> #endif
> #if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
> #if (BUTTON_5_LONG == CMD_SLEEPMODE)
> gShutdownButton = 5;
> #endif
> #endif
> #endif
> }
> 
> ```

# Clang-Format

Teil vom [LLVM](https://clang.llvm.org/docs/ClangFormat.html) und wohl der Klassiker unter den Code Format Tools. Hat viele Einstellungsmöglichkeiten und wird von VSCode (bzw dem C++ Plugin) nativ unterstützt. Großes Manko: Hasst den Präprozessor

> **.clang-format**
>
> ```txt
> ---
> BasedOnStyle: WebKit
> AlignArrayOfStructures: Right
> AllowShortEnumsOnASingleLine: false
> AllowShortFunctionsOnASingleLine: InlineOnly
> BreakArrays: false
> Cpp11BracedListStyle: true
> FixNamespaceComments: true
> IncludeBlocks: Regroup
> IncludeCategories:
> - Regex: Arduino.h
> Priority: -1
> CaseSensitive: true
> SortPriority: -1
> - Regex: ^"
> Priority: 1
> - Regex: .*
> Priority: 4
> IncludeIsMainRegex: (_test)?$
> IndentCaseLabels: true
> IndentPPDirectives: BeforeHash
> IndentWidth: 8
> InsertBraces: true
> NamespaceIndentation: None
> PointerAlignment: Right
> SpaceAfterCStyleCast: true
> UseTab: Always
> 
> ```

  

> **Ergebnis**
>
> ```cpp
> #include <Arduino.h>
> 
> #include "Button.h"
> #include "Cmd.h"
> #include "Log.h"
> #include "Port.h"
> #include "System.h"
> #include "settings.h"
> 
> bool gButtonInitComplete = false;
> 
> // Only enable those buttons that are not disabled (99 or >115)
> // 0 -> 39: GPIOs
> // 100 -> 115: Port-expander
> #if (NEXT_BUTTON >= 0 && NEXT_BUTTON <= MAX_GPIO)
> #define BUTTON_0_ENABLE
> #elif (NEXT_BUTTON >= 100 && NEXT_BUTTON <= 115)
> #define EXPANDER_0_ENABLE
> #endif
> 
> class z {
> public:
> z() { }
> void doStuff(int z) { return l; }
> };
> 
> t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
> uint8_t gShutdownButton = 99; // Helper used for Neopixel: stores button-number of shutdown-button
> uint16_t gLongPressTime = 0;
> 
> #ifdef PORT_EXPANDER_ENABLE
> extern bool Port_AllowReadFromPortExpander;
> #endif
> 
> static volatile SemaphoreHandle_t Button_TimerSemaphore;
> 
> void Button_Init()
> {
> #if (WAKEUP_BUTTON >= 0 && WAKEUP_BUTTON <= MAX_GPIO)
> if (ESP_ERR_INVALID_ARG == esp_sleep_enable_ext0_wakeup((gpio_num_t) WAKEUP_BUTTON, 0)) {
> snprintf(Log_Buffer, Log_BufferLength, "%s (GPIO: %u)", (char *) FPSTR(wrongWakeUpGpio), WAKEUP_BUTTON);
> Log_Println(Log_Buffer, LOGLEVEL_ERROR);
> }
> #endif
> 
> if (x) {
> y = z;
> }
> 
> switch (a) {
> case b:
> break;
> }
> 
> for (int i = 0; i < 5; i++) {
> i--;
> }
> 
> #ifdef NEOPIXEL_ENABLE // Try to find button that is used for shutdown via longpress-action (only necessary for Neopixel)
> #if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
> #if (BUTTON_0_LONG == CMD_SLEEPMODE)
> gShutdownButton = 0;
> #endif
> #endif
> #if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
> #if (BUTTON_1_LONG == CMD_SLEEPMODE)
> gShutdownButton = 1;
> #endif
> #endif
> #if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
> #if (BUTTON_2_LONG == CMD_SLEEPMODE)
> gShutdownButton = 2;
> #endif
> #endif
> #if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
> #if (BUTTON_3_LONG == CMD_SLEEPMODE)
> gShutdownButton = 3;
> #endif
> #endif
> #if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
> #if (BUTTON_4_LONG == CMD_SLEEPMODE)
> gShutdownButton = 4;
> #endif
> #endif
> #if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
> #if (BUTTON_5_LONG == CMD_SLEEPMODE)
> gShutdownButton = 5;
> #endif
> #endif
> #endif
> }
> 
> ```

### Vorteile

Clang kann gut mit dem c und c++ Syntax umgehen. Es hat sehr viele Konfigurationsmöglichkeiten und (wahrscheinlich der größte Plus-Punkt), es ist von Haus aus in VSCode verfügbar. Auch ist es recht einfach es in [Github Actions](https://github.com/jidicula/clang-format-action) einzubinden (buut, I’ve never done that).

### Nachteile

Clang-Format geht (wie auch die anderen Formatter) sehr stiefmütterlich mit Makros um. Es ist schon schwer ihn zu überreden diese einzurücken, aber folgenden Style geht einfach nicht:

```cpp
void x() {
	#if x
		y = 0;
	#else
		y = 1;
	#endif
}

```

## AStyle

Abürzung für [Artistic Style](https://astyle.sourceforge.net/). Hatte bis vor paar Wochen nichts von ihm gehört, aber es scheint relativ verbreitet zu sein und wird auch aktiv gepfelgt. Eine Unterstützung in VSCode muss sowohl Asytle (das Kommandozeilen Tool) als auch als Plugin [Astyle](https://marketplace.visualstudio.com/items?itemName=chiehyu.vscode-astyle) installiert und konfiguriert werden.

> **.astylerc**
>
> ```txt
> -A2
> --indent=tab
> --indent-switches
> --attach-closing-while
> --indent-modifiers
> --indent-preproc-cond
> --indent-preproc-block
> --indent-col1-comments
> --min-conditional-indent=2
> --pad-comma
> --align-pointer=name
> --align-reference=name
> --break-one-line-headers
> --add-braces
> --attach-return-type-decl
> --max-code-length=220
> 
> ```

  

> **Ergebnis**
>
> ```cpp
> #include <Arduino.h>
> #include "settings.h"
> #include "Log.h"
> #include "Button.h"
> #include "Cmd.h"
> #include "Port.h"
> #include "System.h"
> 
> bool gButtonInitComplete = false;
> 
> // Only enable those buttons that are not disabled (99 or >115)
> // 0 -> 39: GPIOs
> // 100 -> 115: Port-expander
> #if (NEXT_BUTTON >= 0 && NEXT_BUTTON <= MAX_GPIO)
> #define BUTTON_0_ENABLE
> #elif (NEXT_BUTTON >= 100 && NEXT_BUTTON <= 115)
> #define EXPANDER_0_ENABLE
> #endif
> 
> class z {
> public:
> z() { }
> void doStuff(int z) {
> return l;
> }
> };
> 
> t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
> uint8_t gShutdownButton = 99; // Helper used for Neopixel: stores button-number of shutdown-button
> uint16_t gLongPressTime = 0;
> 
> #ifdef PORT_EXPANDER_ENABLE
> extern bool Port_AllowReadFromPortExpander;
> #endif
> 
> static volatile SemaphoreHandle_t Button_TimerSemaphore;
> 
> void Button_Init() {
> #if (WAKEUP_BUTTON >= 0 && WAKEUP_BUTTON <= MAX_GPIO)
> if (ESP_ERR_INVALID_ARG == esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKEUP_BUTTON, 0)) {
> snprintf(Log_Buffer, Log_BufferLength, "%s (GPIO: %u)", (char *) FPSTR(wrongWakeUpGpio), WAKEUP_BUTTON);
> Log_Println(Log_Buffer, LOGLEVEL_ERROR);
> }
> #endif
> 
> if (x) {
> y = z;
> }
> 
> switch (a) {
> case b:
> break;
> }
> 
> for (int i = 0; i < 5; i++) {
> i--;
> }
> 
> #ifdef NEOPIXEL_ENABLE // Try to find button that is used for shutdown via longpress-action (only necessary for Neopixel)
> #if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
> #if (BUTTON_0_LONG == CMD_SLEEPMODE)
> gShutdownButton = 0;
> #endif
> #endif
> #if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
> #if (BUTTON_1_LONG == CMD_SLEEPMODE)
> gShutdownButton = 1;
> #endif
> #endif
> #if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
> #if (BUTTON_2_LONG == CMD_SLEEPMODE)
> gShutdownButton = 2;
> #endif
> #endif
> #if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
> #if (BUTTON_3_LONG == CMD_SLEEPMODE)
> gShutdownButton = 3;
> #endif
> #endif
> #if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
> #if (BUTTON_4_LONG == CMD_SLEEPMODE)
> gShutdownButton = 4;
> #endif
> #endif
> #if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
> #if (BUTTON_5_LONG == CMD_SLEEPMODE)
> gShutdownButton = 5;
> #endif
> #endif
> #endif
> }
> 
> ```

### Vorteile

Der Formatter kann Preprozessor direktiven (halwegs) formatieren.

### Nachteile

Das Tool muss manuell installiert und das VSCode Plugin eingestellt werden. Das war bei mir nicht am Einfachsten, aber wahrscheinlich mit einem kleinen How-To machbar.  
Der Formatter hat gefühlt einige Bugs, wie zB wenn Abstände zwischen mathematischen Operatoren gewünscht sind, werden auch Pointer so formatiert (also zb aus `Pointer *p` wird `Pointer * p`).

## Uncrustify

„Gefunden“ durch das UniversalIntendGUI. Sehr viele Einstellungsmöglichkeiten und vielleicht auch ein Volltreffer.

> **uncrustify.cfg**
>
> ```txt
> tok_split_gte=false
> utf8_byte=false
> utf8_force=false
> indent_cmt_with_tabs=true
> indent_align_string=false
> indent_braces=false
> indent_braces_no_func=false
> indent_braces_no_class=false
> indent_braces_no_struct=false
> indent_brace_parent=false
> indent_namespace=false
> indent_extern=false
> indent_class=false
> indent_class_colon=false
> indent_else_if=false
> indent_var_def_cont=false
> indent_func_call_param=false
> indent_func_def_param=false
> indent_func_proto_param=false
> indent_func_class_param=false
> indent_func_ctor_var_param=false
> indent_template_param=false
> indent_func_param_double=false
> indent_relative_single_line_comments=false
> indent_col1_comment=false
> indent_access_spec_body=false
> indent_paren_nl=false
> indent_comma_paren=false
> indent_bool_paren=false
> indent_first_bool_expr=false
> indent_square_nl=false
> indent_preserve_sql=false
> indent_align_assign=true
> sp_balance_nested_parens=false
> align_keep_tabs=false
> align_with_tabs=false
> align_on_tabstop=false
> align_number_left=false
> align_func_params=false
> align_same_func_call_params=false
> align_var_def_colon=false
> align_var_def_attribute=false
> align_var_def_inline=false
> align_right_cmt_mix=false
> align_on_operator=false
> align_mix_var_proto=false
> align_single_line_func=false
> align_single_line_brace=false
> align_nl_cont=false
> align_left_shift=true
> align_oc_decl_colon=false
> nl_collapse_empty_body=false
> nl_assign_leave_one_liners=false
> nl_class_leave_one_liners=false
> nl_enum_leave_one_liners=false
> nl_getset_leave_one_liners=false
> nl_func_leave_one_liners=false
> nl_if_leave_one_liners=false
> nl_multi_line_cond=false
> nl_multi_line_define=false
> nl_before_case=false
> nl_after_case=false
> nl_after_return=false
> nl_after_semicolon=false
> nl_after_brace_open=false
> nl_after_brace_open_cmt=false
> nl_after_vbrace_open=false
> nl_after_vbrace_open_empty=false
> nl_after_brace_close=false
> nl_after_vbrace_close=false
> nl_define_macro=false
> nl_squeeze_ifdef=false
> nl_ds_struct_enum_cmt=false
> nl_ds_struct_enum_close_brace=false
> nl_create_if_one_liner=false
> nl_create_for_one_liner=false
> nl_create_while_one_liner=false
> ls_for_split_full=false
> ls_func_split_full=false
> nl_after_multiline_comment=false
> eat_blanks_after_open_brace=false
> eat_blanks_before_close_brace=false
> mod_full_brace_if_chain=false
> mod_pawn_semicolon=false
> mod_full_paren_if_bool=false
> mod_remove_extra_semicolon=false
> mod_sort_import=false
> mod_sort_using=false
> mod_sort_include=false
> mod_move_case_break=false
> mod_remove_empty_return=false
> cmt_indent_multi=true
> cmt_c_group=false
> cmt_c_nl_start=false
> cmt_c_nl_end=false
> cmt_cpp_group=false
> cmt_cpp_nl_start=false
> cmt_cpp_nl_end=false
> cmt_cpp_to_c=false
> cmt_star_cont=false
> cmt_multi_check_last=true
> cmt_insert_before_preproc=false
> pp_indent_at_level=false
> pp_region_indent_code=false
> pp_if_indent_code=true
> pp_define_at_level=true
> indent_switch_case=4
> newlines=crlf
> indent_with_tabs=2
> sp_arith=add
> sp_assign=add
> sp_assign_default=add
> mod_full_brace_do=force
> mod_full_brace_for=force
> mod_full_brace_function=force
> mod_full_brace_if=force
> mod_full_brace_while=force
> 
> ```

  

> **Ergebnis**
>
> ```cpp
> #include <Arduino.h>
> #include "settings.h"
> #include "Log.h"
> #include "Button.h"
> #include "Cmd.h"
> #include "Port.h"
> #include "System.h"
> 
> bool gButtonInitComplete = false;
> 
> // Only enable those buttons that are not disabled (99 or >115)
> // 0 -> 39: GPIOs
> // 100 -> 115: Port-expander
> #if (NEXT_BUTTON >= 0 && NEXT_BUTTON <= MAX_GPIO)
> #define BUTTON_0_ENABLE
> #elif (NEXT_BUTTON >= 100 && NEXT_BUTTON <= 115)
> #define EXPANDER_0_ENABLE
> #endif
> 
> class z {
> public:
> z() { }
> void doStuff(int z) { return l; }
> };
> 
> t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
> uint8_t gShutdownButton = 99;	// Helper used for Neopixel: stores button-number of shutdown-button
> uint16_t gLongPressTime = 0;
> 
> #ifdef PORT_EXPANDER_ENABLE
> extern bool Port_AllowReadFromPortExpander;
> #endif
> 
> static volatile SemaphoreHandle_t Button_TimerSemaphore;
> 
> void Button_Init() {
> #if (WAKEUP_BUTTON >= 0 && WAKEUP_BUTTON <= MAX_GPIO)
> if (ESP_ERR_INVALID_ARG == esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKEUP_BUTTON, 0)) {
> snprintf(Log_Buffer, Log_BufferLength, "%s (GPIO: %u)", (char *) FPSTR(wrongWakeUpGpio), WAKEUP_BUTTON);
> Log_Println(Log_Buffer, LOGLEVEL_ERROR);
> }
> #endif
> 
> if (x) {
> y = z;
> }
> 
> switch (a) {
> case b:
> break;
> }
> 
> for (int i = 0; i < 5; i++) {
> i--;
> }
> 
> #ifdef NEOPIXEL_ENABLE	// Try to find button that is used for shutdown via longpress-action (only necessary for Neopixel)
> #if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
> #if (BUTTON_0_LONG == CMD_SLEEPMODE)
> gShutdownButton = 0;
> #endif
> #endif
> #if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
> #if (BUTTON_1_LONG == CMD_SLEEPMODE)
> gShutdownButton = 1;
> #endif
> #endif
> #if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
> #if (BUTTON_2_LONG == CMD_SLEEPMODE)
> gShutdownButton = 2;
> #endif
> #endif
> #if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
> #if (BUTTON_3_LONG == CMD_SLEEPMODE)
> gShutdownButton = 3;
> #endif
> #endif
> #if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
> #if (BUTTON_4_LONG == CMD_SLEEPMODE)
> gShutdownButton = 4;
> #endif
> #endif
> #if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
> #if (BUTTON_5_LONG == CMD_SLEEPMODE)
> gShutdownButton = 5;
> #endif
> #endif
> #endif
> }
> 
> ```

### Vorteile

Es gibt ein VSCode Plugin [Uncrustify](https://marketplace.visualstudio.com/items?itemName=zachflower.uncrustify), den ich aber noch nicht ausgetestet habe. Das Tool hat sehr viele Einstellungsmöglichkeiten und wird aktiv entwickelt. Es gibt auch [Github Actions](https://github.com/coleaeason/actions-uncrustify) um commits gegen eine Konfiguration zu testen.

### Nachteile

Der Formatter muss extern instelliert werden, es gibt aber Builds für Linux und Windows (somit ist das kein echter Nachteil sondern eher ein „eh“). Die Masse an Einstellungen ist wortwörtlich erschlagend und ohne der GUI wäre es noch einmal schlimmer da die Parameter nicht selbsterklärend sind.

## Builtin VSCode Formatter

Benutzt Clang, wenn die Datei `.clang-format` nicht gefunden wird, wird das default Style „Visual Studio“ verwendet. Das entspricht der folgenden Config:

```txt
UseTab: (VS Code current setting)
IndentWidth: (VS Code current setting)
BreakBeforeBraces: Allman
AllowShortIfStatementsOnASingleLine: false
IndentCaseLabels: false
ColumnLimit: 0

```

Damit habe ich das nicht weiter betrachtet.

# HTML & Javascript

## Prettier

Meiner Meinung nach eines der besten Formatter für Javascript und HTML. Kann mit fast allem was Web im Namen hat umgehen, HTML, Javascript, TypeScript und JSX werden bei uns wohl die wichtigsten sein (eine ausführliche Liste ist in der [Doku](https://prettier.io/docs/en/) zu finden). Es hat sehr viele Einstellungsmöglichkeiten und kann auch durch ein Config-File gesteuert werden.

  
  

TL;DR  
Das sind meine gefunden Tools. Aktuell liebäuge ich mit Uncrustify, aber ich bin für Ideen offen, wenn ihr noch andere Tools für die Formatierung kennt. Was halt sehr angenehm wäre, wenn wir zu 100% Toolgestützt sind. Dann muss keine Zeit verbraten werden nur um die Formatierung richtig zu ziehen (ich erwische mich immer, dass ich reflexartig SHIFT+ALT+F drücke und die Formatierung zerstöre 😆)

---

_[View the full topic](https://forum.espuino.de/t/automatische-code-formatierung/1908)._
