From 0ade7097171679a4775c8db998a9a4a7b627aa0a Mon Sep 17 00:00:00 2001
From: David Hebbeker <david@hebbeker.info>
Date: Thu, 13 Apr 2023 13:22:06 +0200
Subject: [PATCH 1/3] Add style configuration for code formatter Clang-Format.

Style is based on style 'Microsoft' which has the greatest resemblance with Allman indentation style, from the available predefined styles.

https://clang.llvm.org/docs/ClangFormatStyleOptions.html#basedonstyle
---
 .clang-format | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 .clang-format

diff --git a/.clang-format b/.clang-format
new file mode 100644
index 000000000..40648db08
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,5 @@
+# Style configuration for code formatter Clang-Format (part of LLVM)
+BasedOnStyle: Microsoft
+ReflowComments: false
+ColumnLimit: 0
+

From bfacf34ad35253c79327721292834080f908c524 Mon Sep 17 00:00:00 2001
From: David Hebbeker <david@hebbeker.info>
Date: Thu, 13 Apr 2023 13:40:14 +0200
Subject: [PATCH 2/3] Apply automatic code formating using clang-format.

In directory time-tracker-src/

    find . -iname '*.h' -o  -iname '*.hpp' -o -iname '*.c' -o -iname '*.cpp' -o -iname '*.ino' | xargs clang-format -i --style=file --fallback-style=none --verbose
---
 time-tracker-pio/include/main.hpp         |   4 +-
 time-tracker-pio/include/pitches.hpp      |   2 +-
 time-tracker-pio/src/display.cpp          | 141 +++++++++++-----------
 time-tracker-pio/src/main.cpp             | 111 ++++++++---------
 time-tracker-pio/src/time-tracker-src.ino |   4 +-
 5 files changed, 134 insertions(+), 128 deletions(-)

diff --git a/time-tracker-pio/include/main.hpp b/time-tracker-pio/include/main.hpp
index 6a092f084..16535fc78 100644
--- a/time-tracker-pio/include/main.hpp
+++ b/time-tracker-pio/include/main.hpp
@@ -3,8 +3,8 @@
 
 namespace main
 {
-void setup(const char * const programIdentificationString);
+void setup(const char *const programIdentificationString);
 void loop();
-}
+} // namespace main
 
 #endif /* APPLICATION_MAIN_HPP_ */
diff --git a/time-tracker-pio/include/pitches.hpp b/time-tracker-pio/include/pitches.hpp
index b9c9e7b6d..d46c0e974 100644
--- a/time-tracker-pio/include/pitches.hpp
+++ b/time-tracker-pio/include/pitches.hpp
@@ -93,4 +93,4 @@ constexpr std::uint16_t C8 = 4186;
 constexpr std::uint16_t CS8 = 4435;
 constexpr std::uint16_t D8 = 4699;
 constexpr std::uint16_t DS8 = 4978;
-}
+} // namespace note
diff --git a/time-tracker-pio/src/display.cpp b/time-tracker-pio/src/display.cpp
index 076012939..3b30c380f 100644
--- a/time-tracker-pio/src/display.cpp
+++ b/time-tracker-pio/src/display.cpp
@@ -1,103 +1,108 @@
 
-#include <Wire.h>
-#include <Arduino.h>
 #include <Adafruit_SSD1306.h>
+#include <Arduino.h>
+#include <Wire.h>
 
 #define SCREEN_WIDTH 128 // OLED display width, in pixels
 #define SCREEN_HEIGHT 64 // OLED display height, in pixels
 
 // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
-#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
+#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
-#define NUMFLAKES     10 // Number of snowflakes in the animation example
+#define NUMFLAKES 10 // Number of snowflakes in the animation example
 
-#define LOGO_HEIGHT   16
-#define LOGO_WIDTH    16
+#define LOGO_HEIGHT 16
+#define LOGO_WIDTH 16
 static constexpr unsigned char PROGMEM logo_bmp[] =
-{ B00000000, B11000000,
-  B00000001, B11000000,
-  B00000001, B11000000,
-  B00000011, B11100000,
-  B11110011, B11100000,
-  B11111110, B11111000,
-  B01111110, B11111111,
-  B00110011, B10011111,
-  B00011111, B11111100,
-  B00001101, B01110000,
-  B00011011, B10100000,
-  B00111111, B11100000,
-  B00111111, B11110000,
-  B01111100, B11110000,
-  B01110000, B01110000,
-  B00000000, B00110000 };
-
-
-#define XPOS   0 // Indexes into the 'icons' array in function below
-#define YPOS   1
+    {B00000000, B11000000,
+     B00000001, B11000000,
+     B00000001, B11000000,
+     B00000011, B11100000,
+     B11110011, B11100000,
+     B11111110, B11111000,
+     B01111110, B11111111,
+     B00110011, B10011111,
+     B00011111, B11111100,
+     B00001101, B01110000,
+     B00011011, B10100000,
+     B00111111, B11100000,
+     B00111111, B11110000,
+     B01111100, B11110000,
+     B01110000, B01110000,
+     B00000000, B00110000};
+
+#define XPOS 0 // Indexes into the 'icons' array in function below
+#define YPOS 1
 #define DELTAY 2
 
 static int8_t icons[NUMFLAKES][3];
 
-void testanimate() {
-  int8_t f;
+void testanimate()
+{
+    int8_t f;
 
     display.clearDisplay(); // Clear the display buffer
 
     // Draw each snowflake:
-    for(f=0; f< NUMFLAKES; f++) {
-      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, WHITE);
+    for (f = 0; f < NUMFLAKES; f++)
+    {
+        display.drawBitmap(icons[f][XPOS], icons[f][YPOS], logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, WHITE);
     }
 
     display.display(); // Show the display buffer on the screen
 
     // Then update coordinates of each flake...
-    for(f=0; f< NUMFLAKES; f++) {
-      icons[f][YPOS] += icons[f][DELTAY];
-      // If snowflake is off the bottom of the screen...
-      if (icons[f][YPOS] >= display.height()) {
-        // Reinitialize to a random position, just off the top
-        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
-        icons[f][YPOS]   = -LOGO_HEIGHT;
-        icons[f][DELTAY] = random(1, 6);
-      }
+    for (f = 0; f < NUMFLAKES; f++)
+    {
+        icons[f][YPOS] += icons[f][DELTAY];
+        // If snowflake is off the bottom of the screen...
+        if (icons[f][YPOS] >= display.height())
+        {
+            // Reinitialize to a random position, just off the top
+            icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+            icons[f][YPOS] = -LOGO_HEIGHT;
+            icons[f][DELTAY] = random(1, 6);
+        }
     }
 }
 
+void setup_display()
+{
 
-void setup_display() {
-
-  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
-  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
-    Serial.println(F("SSD1306 allocation failed"));
-    for(;;); // Don't proceed, loop forever
-  }
+    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
+    if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))
+    {
+        Serial.println(F("SSD1306 allocation failed"));
+        for (;;)
+            ; // Don't proceed, loop forever
+    }
 
-  // Show initial display buffer contents on the screen --
-  // the library initializes this with an Adafruit splash screen.
-  display.display();
-  delay(2000); // Pause for 2 seconds
+    // Show initial display buffer contents on the screen --
+    // the library initializes this with an Adafruit splash screen.
+    display.display();
+    delay(2000); // Pause for 2 seconds
 
-  // Clear the buffer
-  //display.clearDisplay();
+    // Clear the buffer
+    //display.clearDisplay();
 
-  // Show the display buffer on the screen. You MUST call display() after
-  // drawing commands to make them visible on screen!
-  display.display();
+    // Show the display buffer on the screen. You MUST call display() after
+    // drawing commands to make them visible on screen!
+    display.display();
 
     int8_t f;
 
-  // Initialize 'snowflake' positions
-  for(f=0; f< NUMFLAKES; f++) {
-    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
-    icons[f][YPOS]   = -LOGO_HEIGHT;
-    icons[f][DELTAY] = random(1, 6);
-    Serial.print(F("x: "));
-    Serial.print(icons[f][XPOS], DEC);
-    Serial.print(F(" y: "));
-    Serial.print(icons[f][YPOS], DEC);
-    Serial.print(F(" dy: "));
-    Serial.println(icons[f][DELTAY], DEC);
-  }
-
+    // Initialize 'snowflake' positions
+    for (f = 0; f < NUMFLAKES; f++)
+    {
+        icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
+        icons[f][YPOS] = -LOGO_HEIGHT;
+        icons[f][DELTAY] = random(1, 6);
+        Serial.print(F("x: "));
+        Serial.print(icons[f][XPOS], DEC);
+        Serial.print(F(" y: "));
+        Serial.print(icons[f][YPOS], DEC);
+        Serial.print(F(" dy: "));
+        Serial.println(icons[f][DELTAY], DEC);
+    }
 }
diff --git a/time-tracker-pio/src/main.cpp b/time-tracker-pio/src/main.cpp
index 263895ab3..d28788999 100644
--- a/time-tracker-pio/src/main.cpp
+++ b/time-tracker-pio/src/main.cpp
@@ -3,53 +3,53 @@
 #include "pitches.hpp"
 //#include <ESP32Tone.h>
 #include <Arduino.h>
-#include <cstdint>
 #include <cmath>
+#include <cstdint>
 
 namespace OutputShiftRegister
 {
-  constexpr int pin_data = 14;
-  constexpr int pin_latch = 13;
-  constexpr int pin_clock = 5;
+constexpr int pin_data = 14;
+constexpr int pin_latch = 13;
+constexpr int pin_clock = 5;
 
-  void setup()
-  {
+void setup()
+{
     pinMode(pin_data, OUTPUT);
     pinMode(pin_latch, OUTPUT);
     pinMode(pin_clock, OUTPUT);
-  }
+}
 
-  void setRegister(const uint8_t data)
-  {
+void setRegister(const uint8_t data)
+{
     digitalWrite(pin_latch, LOW);
     shiftOut(pin_data, pin_clock, LSBFIRST, data);
     digitalWrite(pin_latch, HIGH);
-  }
 }
+} // namespace OutputShiftRegister
 
 namespace InputShiftRegister
 {
-  constexpr int pin_data = 34;
-  constexpr int pin_latch = 12;
-  constexpr int pin_clock = 23;
+constexpr int pin_data = 34;
+constexpr int pin_latch = 12;
+constexpr int pin_clock = 23;
 
-  void setup()
-  {
+void setup()
+{
     pinMode(pin_data, INPUT);
     pinMode(pin_latch, OUTPUT);
     pinMode(pin_clock, OUTPUT);
-  }
+}
 
-  typedef decltype(shiftIn(0,0,LSBFIRST)) RegisterType;
+typedef decltype(shiftIn(0, 0, LSBFIRST)) RegisterType;
 
-  RegisterType getRegister()
-  {
+RegisterType getRegister()
+{
     digitalWrite(pin_latch, LOW);
     delayMicroseconds(1); // at least 200ns
     digitalWrite(pin_latch, HIGH);
     return shiftIn(pin_data, pin_clock, LSBFIRST);
-  }
 }
+} // namespace InputShiftRegister
 
 /**
  *
@@ -57,47 +57,48 @@ namespace InputShiftRegister
  */
 static std::uint8_t getEvent()
 {
-  static InputShiftRegister::RegisterType oldValue = 0;
-  const InputShiftRegister::RegisterType newValue = InputShiftRegister::getRegister();
-  std::uint8_t result = 0;
-  if(newValue != 0 && oldValue == 0)
-  {
-    result = std::log2(newValue<<1);
-  }
-  oldValue = newValue;
-  return result;
+    static InputShiftRegister::RegisterType oldValue = 0;
+    const InputShiftRegister::RegisterType newValue = InputShiftRegister::getRegister();
+    std::uint8_t result = 0;
+    if (newValue != 0 && oldValue == 0)
+    {
+        result = std::log2(newValue << 1);
+    }
+    oldValue = newValue;
+    return result;
 }
 
 constexpr int pin_buzzer = 4;
 
-namespace main{
-void setup(char const * programIdentificationString)
+namespace main
 {
-  // put your setup code here, to run once:
-  pinMode(pin_buzzer, OUTPUT);
-  OutputShiftRegister::setup();
-  InputShiftRegister::setup();
-  setup_display();
-  Serial.begin(115200);
-  delay(100);
-  Serial.flush();
-  delay(100);
-  Serial.printf("\n begin program '%s'\n", programIdentificationString);
+void setup(char const *programIdentificationString)
+{
+    // put your setup code here, to run once:
+    pinMode(pin_buzzer, OUTPUT);
+    OutputShiftRegister::setup();
+    InputShiftRegister::setup();
+    setup_display();
+    Serial.begin(115200);
+    delay(100);
+    Serial.flush();
+    delay(100);
+    Serial.printf("\n begin program '%s'\n", programIdentificationString);
 }
 void loop()
 {
-  const auto event = getEvent();
-  if (event)
-  {
-    constexpr std::uint16_t notes[] = { note::C4, note::G3, note::A3, note::B3, note::D1, note::E1, note::F1, note::G1 };
-    OutputShiftRegister::setRegister(1 << (event - 1));
-    tone(pin_buzzer, notes[event-1], 250);
-  }
-  else
-  {
-    OutputShiftRegister::setRegister(0);
-  }
-  delay(100);
-  testanimate(); // Animate bitmaps
-}
+    const auto event = getEvent();
+    if (event)
+    {
+        constexpr std::uint16_t notes[] = {note::C4, note::G3, note::A3, note::B3, note::D1, note::E1, note::F1, note::G1};
+        OutputShiftRegister::setRegister(1 << (event - 1));
+        tone(pin_buzzer, notes[event - 1], 250);
+    }
+    else
+    {
+        OutputShiftRegister::setRegister(0);
+    }
+    delay(100);
+    testanimate(); // Animate bitmaps
 }
+} // namespace main
diff --git a/time-tracker-pio/src/time-tracker-src.ino b/time-tracker-pio/src/time-tracker-src.ino
index f858f1bc7..88318e7b3 100644
--- a/time-tracker-pio/src/time-tracker-src.ino
+++ b/time-tracker-pio/src/time-tracker-src.ino
@@ -4,10 +4,10 @@ const auto programIdentificationString = __FILE__ " compiled at " __DATE__ " " _
 
 void setup()
 {
-  main::setup(programIdentificationString);
+    main::setup(programIdentificationString);
 }
 
 void loop()
 {
-  main::loop();
+    main::loop();
 }

From 9d5ceb96fd8478f99869f188524a08052a98c74c Mon Sep 17 00:00:00 2001
From: David Hebbeker <david@hebbeker.info>
Date: Thu, 13 Apr 2023 14:18:59 +0200
Subject: [PATCH 3/3] Add GitHub Action to automatically check the code
 formatting.

Based on example from: https://github.com/jidicula/clang-format-action/tree/7ad9af69dbdc0ca5f5caf0c2efc0d8f6c8322153#single-path
---
 .github/workflows/clang-format-check.yml | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 .github/workflows/clang-format-check.yml

diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml
new file mode 100644
index 000000000..9ad9508e0
--- /dev/null
+++ b/.github/workflows/clang-format-check.yml
@@ -0,0 +1,13 @@
+name: Clang-Format Check
+on: [push, pull_request]
+jobs:
+  formatting-check:
+    name: check style formatting
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v3
+    - name: Run clang-format style check.
+      uses: jidicula/clang-format-action@v4.11.0
+      with:
+        fallback-style: 'none'
+
