Skip to content

Commit bba1758

Browse files
committed
littlefs-do: Generate list_settings.cpp from Settings.h
Add and use the python script `parse_infinitime_settings.py` to generate the file `list_settings.cpp` with helper function `list_settings()` to reduce the maintenance burden by not having to manually handle changes in `Settings.h`. Fixes: #54
1 parent 0fe5b87 commit bba1758

File tree

3 files changed

+174
-79
lines changed

3 files changed

+174
-79
lines changed

CMakeLists.txt

+22
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,28 @@ target_link_libraries(littlefs-do PUBLIC littlefs)
337337
target_link_libraries(littlefs-do PRIVATE SDL2::SDL2)
338338
target_link_libraries(littlefs-do PRIVATE infinitime_fonts)
339339

340+
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
341+
# FindPython3 module introduces with CMake 3.12
342+
# https://cmake.org/cmake/help/latest/module/FindPython3.html
343+
find_package(Python3 REQUIRED)
344+
else()
345+
set(Python3_EXECUTABLE "python")
346+
endif()
347+
message(STATUS "calling ${CMAKE_CURRENT_SOURCE_DIR}/parse_infinitime_settings.py generating ${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp")
348+
add_custom_command(
349+
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp
350+
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/parse_infinitime_settings.py
351+
"${InfiniTime_DIR}/src/components/settings/Settings.h"
352+
--output "${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp"
353+
DEPENDS "${InfiniTime_DIR}/src/components/settings/Settings.h"
354+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
355+
)
356+
add_custom_target(list_settings
357+
DEPENDS "${InfiniTime_DIR}/src/components/settings/Settings.h"
358+
)
359+
target_sources(littlefs-do PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp")
360+
add_dependencies(littlefs-do list_settings)
361+
340362
add_subdirectory(external/miniz)
341363
add_subdirectory(external/nlohmann_json)
342364
target_link_libraries(littlefs-do PRIVATE miniz)

littlefs-do-main.cpp

+4-79
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,9 @@ int command_cp(const std::string &program_name, const std::vector<std::string> &
515515
return 0;
516516
}
517517

518+
// generated into ${CMAKE_BUILD_DIR}/list_settings.cpp
519+
void list_settings(const Pinetime::Controllers::Settings &settingsController);
520+
518521
int command_settings(const std::string &program_name, const std::vector<std::string> &args, bool verbose)
519522
{
520523
if (verbose) {
@@ -533,85 +536,7 @@ int command_settings(const std::string &program_name, const std::vector<std::str
533536
std::cout << "calling Settings::Init()" << std::endl;
534537
}
535538
settingsController.Init();
536-
using namespace Pinetime::Controllers;
537-
{
538-
auto clockface = settingsController.GetClockFace();
539-
auto clockface_str = [](auto val) {
540-
if (val == 0) return "Digital";
541-
if (val == 1) return "Analog";
542-
if (val == 2) return "PineTimeStyle";
543-
if (val == 3) return "Terminal";
544-
return "unknown";
545-
}(clockface);
546-
std::cout << "ClockFace: " << static_cast<int>(clockface) << " " << clockface_str << std::endl;
547-
}
548-
{
549-
auto chimes = settingsController.GetChimeOption();
550-
auto chimes_str = [](auto val) {
551-
if (val == Settings::ChimesOption::None) return "None";
552-
if (val == Settings::ChimesOption::Hours) return "Hours";
553-
if (val == Settings::ChimesOption::HalfHours) return "HalfHours";
554-
return "unknown";
555-
}(chimes);
556-
std::cout << "Chimes: " << static_cast<int>(chimes) << " " << chimes_str << std::endl;
557-
}
558-
auto color_str = [](auto c) {
559-
if (c == Settings::Colors::White) return "White";
560-
if (c == Settings::Colors::Silver) return "Silver";
561-
if (c == Settings::Colors::Gray) return "Gray";
562-
if (c == Settings::Colors::Black) return "Black";
563-
if (c == Settings::Colors::Red) return "Red";
564-
if (c == Settings::Colors::Maroon) return "Maroon";
565-
if (c == Settings::Colors::Yellow) return "Yellow";
566-
if (c == Settings::Colors::Olive) return "Olive";
567-
if (c == Settings::Colors::Lime) return "Lime";
568-
if (c == Settings::Colors::Green) return "Cyan";
569-
if (c == Settings::Colors::Teal) return "Teal";
570-
if (c == Settings::Colors::Blue) return "Blue";
571-
if (c == Settings::Colors::Navy) return "Navy";
572-
if (c == Settings::Colors::Magenta) return "Magenta";
573-
if (c == Settings::Colors::Purple) return "Purple";
574-
if (c == Settings::Colors::Orange) return "Orange";
575-
return "unknown";
576-
};
577-
std::cout << "PTSColorTime: " << color_str(settingsController.GetPTSColorTime()) << std::endl;
578-
std::cout << "PTSColorBar: " << color_str(settingsController.GetPTSColorBar()) << std::endl;
579-
std::cout << "PTSColorBG: " << color_str(settingsController.GetPTSColorBG()) << std::endl;
580-
std::cout << "AppMenu: " << static_cast<int>(settingsController.GetAppMenu()) << std::endl;
581-
std::cout << "SettingsMenu: " << static_cast<int>(settingsController.GetSettingsMenu()) << std::endl;
582-
std::cout << "ClockType: " << (settingsController.GetClockType() == Settings::ClockType::H24 ? "H24" : "H12") << std::endl;
583-
{
584-
auto notif = settingsController.GetNotificationStatus();
585-
auto notif_str = [](auto val) {
586-
if (val == Settings::Notification::On) return "On";
587-
if (val == Settings::Notification::Off) return "Off";
588-
if (val == Settings::Notification::Sleep) return "Sleep";
589-
return "unknown";
590-
}(notif);
591-
std::cout << "NotificationStatus: " << static_cast<int>(notif) << " " << notif_str << std::endl;
592-
}
593-
std::cout << "ScreenTimeOut: " << settingsController.GetScreenTimeOut() << " ms" << std::endl;
594-
std::cout << "ShakeThreshold: " << settingsController.GetShakeThreshold() << std::endl;
595-
{
596-
std::cout << "WakeUpModes: " << std::endl;
597-
std::cout << "- SingleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::SingleTap) ? "ON" : "OFF") << std::endl;
598-
std::cout << "- DoubleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::DoubleTap) ? "ON" : "OFF") << std::endl;
599-
std::cout << "- RaiseWrist: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::RaiseWrist) ? "ON" : "OFF") << std::endl;
600-
std::cout << "- Shake: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::Shake) ? "ON" : "OFF") << std::endl;
601-
}
602-
{
603-
auto brightness = settingsController.GetBrightness();
604-
auto brightness_str = [](auto val) {
605-
if (val == BrightnessController::Levels::Off) return "Off";
606-
if (val == BrightnessController::Levels::Low) return "Low";
607-
if (val == BrightnessController::Levels::Medium) return "Medium";
608-
if (val == BrightnessController::Levels::High) return "High";
609-
return "unknown";
610-
}(brightness);
611-
std::cout << "Brightness: " << static_cast<int>(brightness) << " " << brightness_str << std::endl;
612-
}
613-
std::cout << "StepsGoal: " << settingsController.GetStepsGoal() << std::endl;
614-
std::cout << "BleRadioEnabled: " << (settingsController.GetBleRadioEnabled() ? "true" : "false") << std::endl;
539+
list_settings(settingsController);
615540
return 0;
616541
}
617542

parse_infinitime_settings.py

+148
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import pathlib
4+
import re
5+
import sys
6+
7+
def main():
8+
parser = argparse.ArgumentParser(description="Parse settings.h and create a status printing c++ file")
9+
parser.add_argument("settings_h_file", type=str,
10+
help="path to 'settings.h' file to parse")
11+
parser.add_argument("-o", "--output", type=str,
12+
help="file to generated write c++ code into",
13+
default="-")
14+
args = parser.parse_args()
15+
16+
with open(args.settings_h_file, encoding="utf-8") as f:
17+
settings = f.read()
18+
enum_matcher = re.compile(r"enum class ([a-zA-Z]+) : uint8_t \{[ \n]*([^}]*)\}\;")
19+
enum_matches = enum_matcher.findall(settings)
20+
21+
# get all enums
22+
def match_to_enum(match):
23+
enum_name = match[0]
24+
entries_str = match[1]
25+
entries = [e.strip() for e in entries_str.split(",")]
26+
entries_filtered = [e.split("=")[0].strip() if "=" in e else e for e in entries if e]
27+
return (enum_name, entries_filtered)
28+
enum_list = [match_to_enum(e) for e in enum_matches]
29+
enums = {key: entries for key, entries in enum_list}
30+
print("extracted enums:")
31+
for e in enums:
32+
print(" ", e, enums[e])
33+
print("")
34+
#print(enums)
35+
36+
# get all Getters
37+
m_getters = re.findall(r"([a-zA-Z_0-9<>]+) ([gG]et[a-zA-Z]+)\(\) const", settings)
38+
print("extracted getter:")
39+
for m in m_getters:
40+
print(" ", m)
41+
print("")
42+
43+
def getter_to_cpp(m_getter, enums):
44+
getter_ret, getter_call = m_getter
45+
setting_name = getter_call[3:]
46+
kwargs = {
47+
"getter_ret": getter_ret,
48+
"getter_call": getter_call,
49+
"setting_name": setting_name,
50+
}
51+
out = ""
52+
53+
if getter_ret in enums:
54+
out += """
55+
{{
56+
auto {setting_name}_str = [](auto val) {{""".format(**kwargs)
57+
enum_items = enums[getter_ret]
58+
for enum_entry in enum_items:
59+
out += """
60+
if (val == Settings::{getter_ret}::{enum_entry}) return "{enum_entry}";""".format(**kwargs, enum_entry=enum_entry)
61+
out += """
62+
return "unknown";
63+
}};
64+
std::cout << "{setting_name}: " << static_cast<int>(settingsController.{getter_call}()) << " " << {setting_name}_str(settingsController.{getter_call}()) << std::endl;
65+
}}""".format(**kwargs)
66+
67+
elif setting_name == "ClockFace":
68+
out += """
69+
{{
70+
auto clockface = settingsController.GetClockFace();
71+
auto clockface_str = [](auto val) {{
72+
if (val == 0) return "Digital";
73+
if (val == 1) return "Analog";
74+
if (val == 2) return "PineTimeStyle";
75+
if (val == 3) return "Terminal";
76+
return "unknown";
77+
}}(clockface);
78+
std::cout << "ClockFace: " << static_cast<int>(clockface) << " " << clockface_str << std::endl;
79+
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)
80+
81+
elif setting_name == "ScreenTimeOut":
82+
out += """
83+
{{
84+
{getter_ret} val = settingsController.{getter_call}();
85+
std::cout << "{setting_name}: " << static_cast<int>(settingsController.{getter_call}()) << " ms" << std::endl;
86+
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)
87+
88+
elif setting_name == "WakeUpModes":
89+
out += """
90+
{{
91+
std::cout << "WakeUpModes: " << std::endl;
92+
std::cout << "- SingleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::SingleTap) ? "ON" : "OFF") << std::endl;
93+
std::cout << "- DoubleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::DoubleTap) ? "ON" : "OFF") << std::endl;
94+
std::cout << "- RaiseWrist: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::RaiseWrist) ? "ON" : "OFF") << std::endl;
95+
std::cout << "- Shake: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::Shake) ? "ON" : "OFF") << std::endl;
96+
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)
97+
98+
elif setting_name == "Brightness":
99+
# Brightness levels are stored in components/brightness/BrightnessController.h
100+
# create special handling
101+
out += """
102+
{
103+
auto brightness = settingsController.GetBrightness();
104+
auto brightness_str = [](auto val) {
105+
if (val == BrightnessController::Levels::Off) return "Off";
106+
if (val == BrightnessController::Levels::Low) return "Low";
107+
if (val == BrightnessController::Levels::Medium) return "Medium";
108+
if (val == BrightnessController::Levels::High) return "High";
109+
return "unknown";
110+
}(brightness);
111+
std::cout << "Brightness: " << static_cast<int>(brightness) << " " << brightness_str << std::endl;
112+
}"""
113+
114+
elif getter_ret == "bool":
115+
out += """
116+
{{
117+
{getter_ret} val = settingsController.{getter_call}();
118+
std::cout << "{setting_name}: " << (settingsController.{getter_call}() ? "true" : "false") << std::endl;
119+
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)
120+
121+
else: # just output non-enum entry
122+
out += """
123+
{{
124+
{getter_ret} val = settingsController.{getter_call}();
125+
std::cout << "{setting_name}: " << static_cast<int>(settingsController.{getter_call}()) << std::endl;
126+
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)
127+
128+
return out
129+
130+
list_settings_function = """
131+
#include <iostream>
132+
#include "components/settings/Settings.h"
133+
void list_settings(const Pinetime::Controllers::Settings &settingsController) {
134+
using namespace Pinetime::Controllers;"""
135+
for m in m_getters:
136+
list_settings_function += getter_to_cpp(m, enums)
137+
138+
list_settings_function += """
139+
}"""
140+
if args.output == "" or args.output == "-":
141+
print(list_settings_function)
142+
else:
143+
with open(args.output, "w", encoding="utf-8") as f:
144+
f.write(list_settings_function)
145+
return 0
146+
147+
if __name__ == '__main__':
148+
sys.exit(main())

0 commit comments

Comments
 (0)