Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

littlefs-do: Generate list_settings.cpp from Settings.h #62

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,28 @@ target_link_libraries(littlefs-do PUBLIC littlefs)
target_link_libraries(littlefs-do PRIVATE SDL2::SDL2)
target_link_libraries(littlefs-do PRIVATE infinitime_fonts)

if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
# FindPython3 module introduces with CMake 3.12
# https://cmake.org/cmake/help/latest/module/FindPython3.html
find_package(Python3 REQUIRED)
else()
set(Python3_EXECUTABLE "python")
endif()
message(STATUS "calling ${CMAKE_CURRENT_SOURCE_DIR}/parse_infinitime_settings.py generating ${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp")
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/parse_infinitime_settings.py
"${InfiniTime_DIR}/src/components/settings/Settings.h"
--output "${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp"
DEPENDS "${InfiniTime_DIR}/src/components/settings/Settings.h"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
add_custom_target(list_settings
DEPENDS "${InfiniTime_DIR}/src/components/settings/Settings.h"
)
target_sources(littlefs-do PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/list_settings.cpp")
add_dependencies(littlefs-do list_settings)

add_subdirectory(external/miniz)
add_subdirectory(external/nlohmann_json)
target_link_libraries(littlefs-do PRIVATE miniz)
Expand Down
83 changes: 4 additions & 79 deletions littlefs-do-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,9 @@ int command_cp(const std::string &program_name, const std::vector<std::string> &
return 0;
}

// generated into ${CMAKE_BUILD_DIR}/list_settings.cpp
void list_settings(const Pinetime::Controllers::Settings &settingsController);

int command_settings(const std::string &program_name, const std::vector<std::string> &args, bool verbose)
{
if (verbose) {
Expand All @@ -533,85 +536,7 @@ int command_settings(const std::string &program_name, const std::vector<std::str
std::cout << "calling Settings::Init()" << std::endl;
}
settingsController.Init();
using namespace Pinetime::Controllers;
{
auto clockface = settingsController.GetClockFace();
auto clockface_str = [](auto val) {
if (val == 0) return "Digital";
if (val == 1) return "Analog";
if (val == 2) return "PineTimeStyle";
if (val == 3) return "Terminal";
return "unknown";
}(clockface);
std::cout << "ClockFace: " << static_cast<int>(clockface) << " " << clockface_str << std::endl;
}
{
auto chimes = settingsController.GetChimeOption();
auto chimes_str = [](auto val) {
if (val == Settings::ChimesOption::None) return "None";
if (val == Settings::ChimesOption::Hours) return "Hours";
if (val == Settings::ChimesOption::HalfHours) return "HalfHours";
return "unknown";
}(chimes);
std::cout << "Chimes: " << static_cast<int>(chimes) << " " << chimes_str << std::endl;
}
auto color_str = [](auto c) {
if (c == Settings::Colors::White) return "White";
if (c == Settings::Colors::Silver) return "Silver";
if (c == Settings::Colors::Gray) return "Gray";
if (c == Settings::Colors::Black) return "Black";
if (c == Settings::Colors::Red) return "Red";
if (c == Settings::Colors::Maroon) return "Maroon";
if (c == Settings::Colors::Yellow) return "Yellow";
if (c == Settings::Colors::Olive) return "Olive";
if (c == Settings::Colors::Lime) return "Lime";
if (c == Settings::Colors::Green) return "Cyan";
if (c == Settings::Colors::Teal) return "Teal";
if (c == Settings::Colors::Blue) return "Blue";
if (c == Settings::Colors::Navy) return "Navy";
if (c == Settings::Colors::Magenta) return "Magenta";
if (c == Settings::Colors::Purple) return "Purple";
if (c == Settings::Colors::Orange) return "Orange";
return "unknown";
};
std::cout << "PTSColorTime: " << color_str(settingsController.GetPTSColorTime()) << std::endl;
std::cout << "PTSColorBar: " << color_str(settingsController.GetPTSColorBar()) << std::endl;
std::cout << "PTSColorBG: " << color_str(settingsController.GetPTSColorBG()) << std::endl;
std::cout << "AppMenu: " << static_cast<int>(settingsController.GetAppMenu()) << std::endl;
std::cout << "SettingsMenu: " << static_cast<int>(settingsController.GetSettingsMenu()) << std::endl;
std::cout << "ClockType: " << (settingsController.GetClockType() == Settings::ClockType::H24 ? "H24" : "H12") << std::endl;
{
auto notif = settingsController.GetNotificationStatus();
auto notif_str = [](auto val) {
if (val == Settings::Notification::On) return "On";
if (val == Settings::Notification::Off) return "Off";
if (val == Settings::Notification::Sleep) return "Sleep";
return "unknown";
}(notif);
std::cout << "NotificationStatus: " << static_cast<int>(notif) << " " << notif_str << std::endl;
}
std::cout << "ScreenTimeOut: " << settingsController.GetScreenTimeOut() << " ms" << std::endl;
std::cout << "ShakeThreshold: " << settingsController.GetShakeThreshold() << std::endl;
{
std::cout << "WakeUpModes: " << std::endl;
std::cout << "- SingleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::SingleTap) ? "ON" : "OFF") << std::endl;
std::cout << "- DoubleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::DoubleTap) ? "ON" : "OFF") << std::endl;
std::cout << "- RaiseWrist: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::RaiseWrist) ? "ON" : "OFF") << std::endl;
std::cout << "- Shake: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::Shake) ? "ON" : "OFF") << std::endl;
}
{
auto brightness = settingsController.GetBrightness();
auto brightness_str = [](auto val) {
if (val == BrightnessController::Levels::Off) return "Off";
if (val == BrightnessController::Levels::Low) return "Low";
if (val == BrightnessController::Levels::Medium) return "Medium";
if (val == BrightnessController::Levels::High) return "High";
return "unknown";
}(brightness);
std::cout << "Brightness: " << static_cast<int>(brightness) << " " << brightness_str << std::endl;
}
std::cout << "StepsGoal: " << settingsController.GetStepsGoal() << std::endl;
std::cout << "BleRadioEnabled: " << (settingsController.GetBleRadioEnabled() ? "true" : "false") << std::endl;
list_settings(settingsController);
return 0;
}

Expand Down
148 changes: 148 additions & 0 deletions parse_infinitime_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env python3
import argparse
import pathlib
import re
import sys

def main():
parser = argparse.ArgumentParser(description="Parse settings.h and create a status printing c++ file")
parser.add_argument("settings_h_file", type=str,
help="path to 'settings.h' file to parse")
parser.add_argument("-o", "--output", type=str,
help="file to generated write c++ code into",
default="-")
args = parser.parse_args()

with open(args.settings_h_file, encoding="utf-8") as f:
settings = f.read()
enum_matcher = re.compile(r"enum class ([a-zA-Z]+) : uint8_t \{[ \n]*([^}]*)\}\;")
enum_matches = enum_matcher.findall(settings)

# get all enums
def match_to_enum(match):
enum_name = match[0]
entries_str = match[1]
entries = [e.strip() for e in entries_str.split(",")]
entries_filtered = [e.split("=")[0].strip() if "=" in e else e for e in entries if e]
return (enum_name, entries_filtered)
enum_list = [match_to_enum(e) for e in enum_matches]
enums = {key: entries for key, entries in enum_list}
print("extracted enums:")
for e in enums:
print(" ", e, enums[e])
print("")
#print(enums)

# get all Getters
m_getters = re.findall(r"([a-zA-Z_0-9<>]+) ([gG]et[a-zA-Z]+)\(\) const", settings)
print("extracted getter:")
for m in m_getters:
print(" ", m)
print("")

def getter_to_cpp(m_getter, enums):
getter_ret, getter_call = m_getter
setting_name = getter_call[3:]
kwargs = {
"getter_ret": getter_ret,
"getter_call": getter_call,
"setting_name": setting_name,
}
out = ""

if getter_ret in enums:
out += """
{{
auto {setting_name}_str = [](auto val) {{""".format(**kwargs)
enum_items = enums[getter_ret]
for enum_entry in enum_items:
out += """
if (val == Settings::{getter_ret}::{enum_entry}) return "{enum_entry}";""".format(**kwargs, enum_entry=enum_entry)
out += """
return "unknown";
}};
std::cout << "{setting_name}: " << static_cast<int>(settingsController.{getter_call}()) << " " << {setting_name}_str(settingsController.{getter_call}()) << std::endl;
}}""".format(**kwargs)

elif setting_name == "ClockFace":
out += """
{{
auto clockface = settingsController.GetClockFace();
auto clockface_str = [](auto val) {{
if (val == 0) return "Digital";
if (val == 1) return "Analog";
if (val == 2) return "PineTimeStyle";
if (val == 3) return "Terminal";
return "unknown";
}}(clockface);
std::cout << "ClockFace: " << static_cast<int>(clockface) << " " << clockface_str << std::endl;
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)

elif setting_name == "ScreenTimeOut":
out += """
{{
{getter_ret} val = settingsController.{getter_call}();
std::cout << "{setting_name}: " << static_cast<int>(settingsController.{getter_call}()) << " ms" << std::endl;
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)

elif setting_name == "WakeUpModes":
out += """
{{
std::cout << "WakeUpModes: " << std::endl;
std::cout << "- SingleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::SingleTap) ? "ON" : "OFF") << std::endl;
std::cout << "- DoubleTap: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::DoubleTap) ? "ON" : "OFF") << std::endl;
std::cout << "- RaiseWrist: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::RaiseWrist) ? "ON" : "OFF") << std::endl;
std::cout << "- Shake: " << (settingsController.isWakeUpModeOn(Settings::WakeUpMode::Shake) ? "ON" : "OFF") << std::endl;
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)

elif setting_name == "Brightness":
# Brightness levels are stored in components/brightness/BrightnessController.h
# create special handling
out += """
{
auto brightness = settingsController.GetBrightness();
auto brightness_str = [](auto val) {
if (val == BrightnessController::Levels::Off) return "Off";
if (val == BrightnessController::Levels::Low) return "Low";
if (val == BrightnessController::Levels::Medium) return "Medium";
if (val == BrightnessController::Levels::High) return "High";
return "unknown";
}(brightness);
std::cout << "Brightness: " << static_cast<int>(brightness) << " " << brightness_str << std::endl;
}"""

elif getter_ret == "bool":
out += """
{{
{getter_ret} val = settingsController.{getter_call}();
std::cout << "{setting_name}: " << (settingsController.{getter_call}() ? "true" : "false") << std::endl;
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)

else: # just output non-enum entry
out += """
{{
{getter_ret} val = settingsController.{getter_call}();
std::cout << "{setting_name}: " << static_cast<int>(settingsController.{getter_call}()) << std::endl;
}}""".format(getter_ret=getter_ret, getter_call=getter_call, setting_name=setting_name)

return out

list_settings_function = """
#include <iostream>
#include "components/settings/Settings.h"
void list_settings(const Pinetime::Controllers::Settings &settingsController) {
using namespace Pinetime::Controllers;"""
for m in m_getters:
list_settings_function += getter_to_cpp(m, enums)

list_settings_function += """
}"""
if args.output == "" or args.output == "-":
print(list_settings_function)
else:
with open(args.output, "w", encoding="utf-8") as f:
f.write(list_settings_function)
return 0

if __name__ == '__main__':
sys.exit(main())