npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

enamel

v1.2.5

Published

Enamel is a python script that generates C helpers from a [Clay](https://github.com/pebble/clay) configuration file to easily get the value of your settings.

Downloads

38

Readme

Enamel Build Status MIT License

Enamel is a python script that generates C helpers from a Clay configuration file to easily get the value of your settings.

Enamel will :

  • handle AppMessages automatically (app_message_open, handler registration, ...)
  • save/load the value of the settings in the persistant storage automatically
  • provide a getter for each of your settings
  • notify subscribers when settings are received from Clay

You can focus on your watchapp/face, Enamel will do the rest !


Getting Started (SDK 3.13+)

  1. You project must contain a valid configuration file in src/js/config.json (see https://github.com/pebble/clay)
  2. Install enamel with pebble package install enamel
  3. Copy and paste the following line into the top of your wscript :
import sys
sys.path.append('node_modules')
from enamel.enamel import enamel
  1. Change the build of your wscript from
ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), target=app_elf)

to

ctx(rule = enamel, source='src/js/config.json', target=['enamel.c', 'enamel.h'])
ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c') + ['enamel.c'], target=app_elf)
  1. Launch your Pebble build : 2 files (enamel.c and enamel.h) should be generated in build and compiled

:warning: The first time you launch a build, you will get an error message because Jinja2 module is missing. Just follow the instructions to fix your environment.

Getting Started (CloudPebble)

In the CloudPebble environment, you can't modify the wscript so you need to call directly the python script.

  1. Under Dependencies in the project navigation, enter enamel as the Package Name and ^1.0.0 for the Version. You may use any specific version you like, however using ^1.0.0 will ensure you receive all minor version updates.

  2. Copy the content of your Clay's config.js file into a local file (local_config.js)

  3. Install the python dependencies for the code generation

pip install -r requirements.txt
  1. Call the script to generate the enamel files
python enamel.py --config /path/to/local_config.js 
  1. Copy the 2 generated files in your CloudPebble project

Using Enamel

  1. Setup your project correctly for Clay : https://github.com/pebble/clay
  2. Include enamel.h in your c file :
#include "enamel.h"
#include <pebble-events/pebble-events.h>
  1. Initialize enamel in your init function and call events_app_message_open() after any other libraries you need to init.
static void init(void) {
  // Initialize Enamel to register App Message handlers and restores settings
  enamel_init();
  
  // call pebble-events app_message_open function
  events_app_message_open(); 
  
  ...
}
  1. Deinitialize enamel in your deinit function :
static void deinit(void) {
  ...

  // Deinit Enamel to unregister App Message handlers and save settings
  enamel_deinit();
}
  1. (Optional) Subscribe with a handler after enamel_init that will be automatically called when the settings are received. Multiple subscribers are supported. Do not forget to unsubscribe before calling enamel_deinit!
static EventHandle s_window_event_handle;
static EventHandle s_text_layer_event_handle;

...

static void enamel_settings_received_window_handler(void *context){
  APP_LOG(0, "Settings received %d", enamel_get_myinteger());
  Window *window = (Window *) context;
  window_set_background_color(window, enamel_get_background());
}

static void enamel_settings_received_text_layer_handler(void *context){
  APP_LOG(0, "Settings received %d", enamel_get_myinteger());
  TextLayer *text_layer = (TextLayer *) context;
  text_layer_set_text_color(text_layer, enamel_get_foreground());
}

...

static void init(void) {
  // Initialize Enamel to register App Message handlers and restores settings
  enamel_init();

  // Subscribe a handler for a window
  s_window_event_handle = enamel_settings_received_subscribe(enamel_settings_received_window_handler, window);

  // Subscribe a handler for a text layer
  s_text_layer_event_handle = enamel_settings_received_subscribe(enamel_settings_received_text_layer_handler, text_layer);
  
  // call pebble-events app_message_open function
  events_app_message_open(); 
  
  ...
}

static void deinit(void) {
    // Unsubscribe from Enamel events
    enamel_settings_received_unsubscribe(s_window_event_handle);
    enamel_settings_received_unsubscribe(s_text_layer_event_handle);

    enamel_deinit();

    ...
}
  1. Get the value of your setting with :
enamel_get_Mysetting(); // where 'Mysetting' is a messageKey in your configuration file

Enamel API

Methods

| Method | Description | |--------|---------| | void enamel_init() | Initialize Enamel and read settings from persistant storage | | void enamel_deinit() | Deinitialize Enamel and save the settings in the persistant storage | | <type> enamel_get_<messageKeyId>() | Return the value for the setting messageKeyId | | bool enamel_get_<messageKeyId>(uint16_t index_) | Only relevant for checkboxgroup. Return the value at given index for the setting messageKeyId |

Type mapping

| Clay Type | Type returned by the getter | |--------|---------| | input | char* | | toggle | bool | | color | GColor | | select/radiogroup | char* or enum | | checkboxgroup | bool | | slider | int32_t |

Special case for select, radiogroup

If the value of the options are string in the config.json, Enamel will generate a char* getter

If the value of the options are integer, Enamel will generate an enum mapping all the possible values for this setting and the getter will return this enum

For the given setting :

{
  "type": "radiogroup",
  "messageKey": "favorite_food",
  "label": "Favorite Food",
  "defaultValue": "1",
  "options": [
    { 
      "label": "Sushi", 
      "value": 0 
    },
    { 
      "label": "Pizza", 
      "value": 1 
    },
    { 
      "label": "Burgers", 
      "value": 2 
    }
  ]
}

Enamel will generate

typedef enum {
	FAVORITE_FOOD_SUSHI = 0,
	FAVORITE_FOOD_PIZZA = 1,
	FAVORITE_FOOD_BURGER = 2,
} FAVORITE_FOODValue;
FAVORITE_FOODValue enamel_get_favorite_food();

You can then easily code switch case for this setting

switch(enamel_get_favorite_food()){
 case FAVORITE_FOOD_SUSHI : break; //do something
 case FAVORITE_FOOD_PIZZA : break; //do something
 case FAVORITE_FOOD_BURGER : break; //do something
}

Special case for slider

Enamel will also generate a constant for your slider containing the 'precision' of your slider, e.g.

#define MY_SLIDER_PRECISION 100