]> git.earman.xyz Git - sensor-watch.git/commitdiff
update 'new watch face' script
authorjoeycastillo <joeycastillo@utexas.edu>
Fri, 11 Oct 2024 00:57:57 +0000 (20:57 -0400)
committerjoeycastillo <joeycastillo@utexas.edu>
Fri, 11 Oct 2024 00:57:57 +0000 (20:57 -0400)
movement/template/template.c [deleted file]
movement/template/template.h [deleted file]
movement/template/watch_face.py [deleted file]
template/template.c [new file with mode: 0644]
template/template.h [new file with mode: 0644]
template/watch_face.py [new file with mode: 0644]
watch-faces.mk

diff --git a/movement/template/template.c b/movement/template/template.c
deleted file mode 100644 (file)
index 4f2e7e1..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) <#year#> <#author_name#>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include "<#watch_face_name#>_face.h"
-
-void <#watch_face_name#>_face_setup(uint8_t watch_face_index, void ** context_ptr) {
-    (void) watch_face_index;
-    if (*context_ptr == NULL) {
-        *context_ptr = malloc(sizeof(<#watch_face_name#>_state_t));
-        memset(*context_ptr, 0, sizeof(<#watch_face_name#>_state_t));
-        // Do any one-time tasks in here; the inside of this conditional happens only at boot.
-    }
-    // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep.
-}
-
-void <#watch_face_name#>_face_activate(void *context) {
-    <#watch_face_name#>_state_t *state = (<#watch_face_name#>_state_t *)context;
-
-    // Handle any tasks related to your watch face coming on screen.
-}
-
-bool <#watch_face_name#>_face_loop(movement_event_t event, void *context) {
-    <#watch_face_name#>_state_t *state = (<#watch_face_name#>_state_t *)context;
-
-    switch (event.event_type) {
-        case EVENT_ACTIVATE:
-            // Show your initial UI here.
-            break;
-        case EVENT_TICK:
-            // If needed, update your display here.
-            break;
-        case EVENT_LIGHT_BUTTON_UP:
-            // You can use the Light button for your own purposes. Note that by default, Movement will also
-            // illuminate the LED in response to EVENT_LIGHT_BUTTON_DOWN; to suppress that behavior, add an
-            // empty case for EVENT_LIGHT_BUTTON_DOWN.
-            break;
-        case EVENT_ALARM_BUTTON_UP:
-            // Just in case you have need for another button.
-            break;
-        case EVENT_TIMEOUT:
-            // Your watch face will receive this event after a period of inactivity. If it makes sense to resign,
-            // you may uncomment this line to move back to the first watch face in the list:
-            // movement_move_to_face(0);
-            break;
-        case EVENT_LOW_ENERGY_UPDATE:
-            // If you did not resign in EVENT_TIMEOUT, you can use this event to update the display once a minute.
-            // Avoid displaying fast-updating values like seconds, since the display won't update again for 60 seconds.
-            // You should also consider starting the tick animation, to show the wearer that this is sleep mode:
-            // watch_start_sleep_animation(500);
-            break;
-        default:
-            // Movement's default loop handler will step in for any cases you don't handle above:
-            // * EVENT_LIGHT_BUTTON_DOWN lights the LED
-            // * EVENT_MODE_BUTTON_UP moves to the next watch face in the list
-            // * EVENT_MODE_LONG_PRESS returns to the first watch face (or skips to the secondary watch face, if configured)
-            // You can override any of these behaviors by adding a case for these events to this switch statement.
-            return movement_default_loop_handler(event);
-    }
-
-    // return true if the watch can enter standby mode. Generally speaking, you should always return true.
-    // Exceptions:
-    //  * If you are displaying a color using the low-level watch_set_led_color function, you should return false.
-    //  * If you are sounding the buzzer using the low-level watch_set_buzzer_on function, you should return false.
-    // Note that if you are driving the LED or buzzer using Movement functions like movement_illuminate_led or
-    // movement_play_alarm, you can still return true. This guidance only applies to the low-level watch_ functions.
-    return true;
-}
-
-void <#watch_face_name#>_face_resign(void *context) {
-    (void) context;
-
-    // handle any cleanup before your watch face goes off-screen.
-}
-
diff --git a/movement/template/template.h b/movement/template/template.h
deleted file mode 100644 (file)
index 7f2612c..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) <#year#> <#author_name#>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef <#WATCH_FACE_NAME#>_FACE_H_
-#define <#WATCH_FACE_NAME#>_FACE_H_
-
-#include "movement.h"
-
-/*
- * A DESCRIPTION OF YOUR WATCH FACE
- *
- * and a description of how use it
- *
- */
-
-typedef struct {
-    // Anything you need to keep track of, put it here!
-    uint8_t unused;
-} <#watch_face_name#>_state_t;
-
-void <#watch_face_name#>_face_setup(uint8_t watch_face_index, void ** context_ptr);
-void <#watch_face_name#>_face_activate(void *context);
-bool <#watch_face_name#>_face_loop(movement_event_t event, void *context);
-void <#watch_face_name#>_face_resign(void *context);
-
-#define <#watch_face_name#>_face ((const watch_face_t){ \
-    <#watch_face_name#>_face_setup, \
-    <#watch_face_name#>_face_activate, \
-    <#watch_face_name#>_face_loop, \
-    <#watch_face_name#>_face_resign, \
-    NULL, \
-})
-
-#endif // <#WATCH_FACE_NAME#>_FACE_H_
-
diff --git a/movement/template/watch_face.py b/movement/template/watch_face.py
deleted file mode 100644 (file)
index 4143b01..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-# MIT License
-#
-# Copyright (c) 2022 David Keck
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-import os
-import re
-import sys
-import datetime
-import argparse
-
-
-MAKEFILE_INDICATOR = "# New watch faces go above this line.\n"
-INCLUDE_INDICATOR = "// New includes go above this line.\n"
-
-
-def replace_placeholders(contents, args):
-    modified_contents = contents.replace("<#WATCH_FACE_NAME#>", args.watch_face_name.upper())
-    modified_contents = modified_contents.replace("<#watch_face_name#>", args.watch_face_name)
-    modified_contents = modified_contents.replace("<#year#>", datetime.datetime.now().strftime("%Y"))
-    if args.author_name:
-        modified_contents = modified_contents.replace("<#author_name#>", " ".join(args.author_name))
-
-    return modified_contents
-
-
-def write_modified_template(args, file_type, output_dir):
-    with open(f"template.{file_type}", 'r') as file_template:
-        file_contents = file_template.read()
-    modified_template = replace_placeholders(file_contents, args)
-    file_path = f"{output_dir}{args.watch_face_name}_face.{file_type}"
-    if not os.path.exists(file_path):
-        with open(file_path, 'w') as output_file:
-            output_file.write(modified_template)
-        print(f"Created {file_path}.")
-    else:
-        print(f"Generation failed: the watch face \"{args.watch_face_name}\" already exists at {file_path}. Unable to generate new files. Exiting...")
-        sys.exit(0)
-
-
-def update_include_file(file_path, indicator_line, line_to_insert):
-    with open(file_path, 'r+') as include_file:
-        include_contents = include_file.readlines()
-        if line_to_insert not in include_contents:
-            new_face_index = include_contents.index(indicator_line)
-            include_contents.insert(new_face_index, line_to_insert)
-            include_file.seek(0)
-            include_file.writelines(include_contents)
-            print(f"Updated {file_path}.")
-        else:
-            print(f"Generation failed: {file_path} already has an entry for {line_to_insert.strip()}. Unable to generate new files. Exiting...")
-            sys.exit(0)
-
-
-def main():
-    parser = argparse.ArgumentParser(description="Create a new watch face.")
-    parser.add_argument("watch_face_type", metavar="face_type", type=str, choices=["clock", "complication", "demo", "sensor", "settings"], help="The type of watch face to create ('clock', 'complication', 'demo', 'sensor', 'settings')")
-    parser.add_argument("watch_face_name", metavar="face_name", type=str, help="The name of the watch face. Use underscores between words if you have more than one.")
-    parser.add_argument("--author-name", metavar="author_name", type=str, nargs='*', help="The name of the author")
-
-    args = parser.parse_args()
-
-    name_valid = re.fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]*', args.watch_face_name)
-    if name_valid is None:
-        print(f"Generation failed: {args.watch_face_name} is not a valid C variable name. Exiting...")
-        sys.exit(0)
-
-    if not args.author_name:
-        print("Note: the \"--author-name\" argument was not supplied via command line. \"<#author_name#>\" will not be replaced in generated template.")
-
-    line_to_insert = f"#include \"{args.watch_face_name}_face.h\"\n"
-    update_include_file(f"..{os.sep}movement_faces.h", INCLUDE_INDICATOR, line_to_insert)
-
-    line_to_insert = f"  ..{os.sep}watch_faces{os.sep}{args.watch_face_type}{os.sep}{args.watch_face_name}_face.c \\\n"
-    update_include_file(f"..{os.sep}make{os.sep}Makefile", MAKEFILE_INDICATOR, line_to_insert)
-
-    output_dir = f"..{os.sep}watch_faces{os.sep}{args.watch_face_type}{os.sep}"
-    write_modified_template(args, "h", output_dir)
-    write_modified_template(args, "c", output_dir)
-
-    print(f"Successfully generated the {args.watch_face_name} {args.watch_face_type} and updated include files.")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/template/template.c b/template/template.c
new file mode 100644 (file)
index 0000000..4f2e7e1
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) <#year#> <#author_name#>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "<#watch_face_name#>_face.h"
+
+void <#watch_face_name#>_face_setup(uint8_t watch_face_index, void ** context_ptr) {
+    (void) watch_face_index;
+    if (*context_ptr == NULL) {
+        *context_ptr = malloc(sizeof(<#watch_face_name#>_state_t));
+        memset(*context_ptr, 0, sizeof(<#watch_face_name#>_state_t));
+        // Do any one-time tasks in here; the inside of this conditional happens only at boot.
+    }
+    // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep.
+}
+
+void <#watch_face_name#>_face_activate(void *context) {
+    <#watch_face_name#>_state_t *state = (<#watch_face_name#>_state_t *)context;
+
+    // Handle any tasks related to your watch face coming on screen.
+}
+
+bool <#watch_face_name#>_face_loop(movement_event_t event, void *context) {
+    <#watch_face_name#>_state_t *state = (<#watch_face_name#>_state_t *)context;
+
+    switch (event.event_type) {
+        case EVENT_ACTIVATE:
+            // Show your initial UI here.
+            break;
+        case EVENT_TICK:
+            // If needed, update your display here.
+            break;
+        case EVENT_LIGHT_BUTTON_UP:
+            // You can use the Light button for your own purposes. Note that by default, Movement will also
+            // illuminate the LED in response to EVENT_LIGHT_BUTTON_DOWN; to suppress that behavior, add an
+            // empty case for EVENT_LIGHT_BUTTON_DOWN.
+            break;
+        case EVENT_ALARM_BUTTON_UP:
+            // Just in case you have need for another button.
+            break;
+        case EVENT_TIMEOUT:
+            // Your watch face will receive this event after a period of inactivity. If it makes sense to resign,
+            // you may uncomment this line to move back to the first watch face in the list:
+            // movement_move_to_face(0);
+            break;
+        case EVENT_LOW_ENERGY_UPDATE:
+            // If you did not resign in EVENT_TIMEOUT, you can use this event to update the display once a minute.
+            // Avoid displaying fast-updating values like seconds, since the display won't update again for 60 seconds.
+            // You should also consider starting the tick animation, to show the wearer that this is sleep mode:
+            // watch_start_sleep_animation(500);
+            break;
+        default:
+            // Movement's default loop handler will step in for any cases you don't handle above:
+            // * EVENT_LIGHT_BUTTON_DOWN lights the LED
+            // * EVENT_MODE_BUTTON_UP moves to the next watch face in the list
+            // * EVENT_MODE_LONG_PRESS returns to the first watch face (or skips to the secondary watch face, if configured)
+            // You can override any of these behaviors by adding a case for these events to this switch statement.
+            return movement_default_loop_handler(event);
+    }
+
+    // return true if the watch can enter standby mode. Generally speaking, you should always return true.
+    // Exceptions:
+    //  * If you are displaying a color using the low-level watch_set_led_color function, you should return false.
+    //  * If you are sounding the buzzer using the low-level watch_set_buzzer_on function, you should return false.
+    // Note that if you are driving the LED or buzzer using Movement functions like movement_illuminate_led or
+    // movement_play_alarm, you can still return true. This guidance only applies to the low-level watch_ functions.
+    return true;
+}
+
+void <#watch_face_name#>_face_resign(void *context) {
+    (void) context;
+
+    // handle any cleanup before your watch face goes off-screen.
+}
+
diff --git a/template/template.h b/template/template.h
new file mode 100644 (file)
index 0000000..3efb201
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) <#year#> <#author_name#>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#pragma once
+
+#include "movement.h"
+
+/*
+ * A DESCRIPTION OF YOUR WATCH FACE
+ *
+ * and a description of how use it
+ *
+ */
+
+typedef struct {
+    // Anything you need to keep track of, put it here!
+    uint8_t unused;
+} <#watch_face_name#>_state_t;
+
+void <#watch_face_name#>_face_setup(uint8_t watch_face_index, void ** context_ptr);
+void <#watch_face_name#>_face_activate(void *context);
+bool <#watch_face_name#>_face_loop(movement_event_t event, void *context);
+void <#watch_face_name#>_face_resign(void *context);
+
+#define <#watch_face_name#>_face ((const watch_face_t){ \
+    <#watch_face_name#>_face_setup, \
+    <#watch_face_name#>_face_activate, \
+    <#watch_face_name#>_face_loop, \
+    <#watch_face_name#>_face_resign, \
+    NULL, \
+})
diff --git a/template/watch_face.py b/template/watch_face.py
new file mode 100644 (file)
index 0000000..26d78cd
--- /dev/null
@@ -0,0 +1,102 @@
+# MIT License
+#
+# Copyright (c) 2022 David Keck
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import os
+import re
+import sys
+import datetime
+import argparse
+
+
+MAKEFILE_INDICATOR = "# New watch faces go above this line.\n"
+INCLUDE_INDICATOR = "// New includes go above this line.\n"
+
+
+def replace_placeholders(contents, args):
+    modified_contents = contents.replace("<#WATCH_FACE_NAME#>", args.watch_face_name.upper())
+    modified_contents = modified_contents.replace("<#watch_face_name#>", args.watch_face_name)
+    modified_contents = modified_contents.replace("<#year#>", datetime.datetime.now().strftime("%Y"))
+    if args.author_name:
+        modified_contents = modified_contents.replace("<#author_name#>", " ".join(args.author_name))
+
+    return modified_contents
+
+
+def write_modified_template(args, file_type, output_dir):
+    with open(f"template.{file_type}", 'r') as file_template:
+        file_contents = file_template.read()
+    modified_template = replace_placeholders(file_contents, args)
+    file_path = f"{output_dir}{args.watch_face_name}_face.{file_type}"
+    if not os.path.exists(file_path):
+        with open(file_path, 'w') as output_file:
+            output_file.write(modified_template)
+        print(f"Created {file_path}.")
+    else:
+        print(f"Generation failed: the watch face \"{args.watch_face_name}\" already exists at {file_path}. Unable to generate new files. Exiting...")
+        sys.exit(0)
+
+
+def update_include_file(file_path, indicator_line, line_to_insert):
+    with open(file_path, 'r+') as include_file:
+        include_contents = include_file.readlines()
+        if line_to_insert not in include_contents:
+            new_face_index = include_contents.index(indicator_line)
+            include_contents.insert(new_face_index, line_to_insert)
+            include_file.seek(0)
+            include_file.writelines(include_contents)
+            print(f"Updated {file_path}.")
+        else:
+            print(f"Generation failed: {file_path} already has an entry for {line_to_insert.strip()}. Unable to generate new files. Exiting...")
+            sys.exit(0)
+
+
+def main():
+    parser = argparse.ArgumentParser(description="Create a new watch face.")
+    parser.add_argument("watch_face_type", metavar="face_type", type=str, choices=["clock", "complication", "demo", "sensor", "settings"], help="The type of watch face to create ('clock', 'complication', 'demo', 'sensor', 'settings')")
+    parser.add_argument("watch_face_name", metavar="face_name", type=str, help="The name of the watch face. Use underscores between words if you have more than one.")
+    parser.add_argument("--author-name", metavar="author_name", type=str, nargs='*', help="The name of the author")
+
+    args = parser.parse_args()
+
+    name_valid = re.fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]*', args.watch_face_name)
+    if name_valid is None:
+        print(f"Generation failed: {args.watch_face_name} is not a valid C variable name. Exiting...")
+        sys.exit(0)
+
+    if not args.author_name:
+        print("Note: the \"--author-name\" argument was not supplied via command line. \"<#author_name#>\" will not be replaced in generated template.")
+
+    line_to_insert = f"#include \"{args.watch_face_name}_face.h\"\n"
+    update_include_file(f"..{os.sep}movement_faces.h", INCLUDE_INDICATOR, line_to_insert)
+
+    line_to_insert = f"  .{os.sep}watch-faces{os.sep}{args.watch_face_type}{os.sep}{args.watch_face_name}_face.c \\\n"
+    update_include_file(f"..{os.sep}watch-faces.mk", MAKEFILE_INDICATOR, line_to_insert)
+
+    output_dir = f"..{os.sep}watch-faces{os.sep}{args.watch_face_type}{os.sep}"
+    write_modified_template(args, "h", output_dir)
+    write_modified_template(args, "c", output_dir)
+
+    print(f"Successfully generated the {args.watch_face_name} {args.watch_face_type} and updated include files.")
+
+
+if __name__ == "__main__":
+    main()
index 98c7ef8c73fdb6b94dc6a692e99327d8c425b0ea..4d2e0fed30ebe15f146c1aea9e3a8d365d553710 100644 (file)
@@ -15,3 +15,4 @@ SRCS += \
   ./watch-faces/sensor/voltage_face.c \
   ./watch-faces/settings/set_time_face.c \
   ./watch-faces/settings/preferences_face.c \
+# New watch faces go above this line.