Skip to content

Commit c4f5e25

Browse files
committed
Merge pull request Hexxeh#19 from pebble/feature-sdk-shell
Feature sdk shell (merge in 2.x)
2 parents 664219f + 2a15650 commit c4f5e25

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

pb-sdk.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python
2+
3+
import argparse
4+
5+
from pebble.PblCommand import PblCommand
6+
from pebble.PblProjectCreator import PblProjectCreator
7+
from pebble.PblBuildCommand import PblBuildCommand
8+
9+
class PbSDKShell:
10+
commands = []
11+
12+
def __init__(self):
13+
self.commands.append(PblProjectCreator())
14+
self.commands.append(PblBuildCommand())
15+
16+
def main(self):
17+
parser = argparse.ArgumentParser(description = 'Pebble SDK Shell')
18+
subparsers = parser.add_subparsers(dest="command", title="Command", description="Action to perform")
19+
for command in self.commands:
20+
subparser = subparsers.add_parser(command.name, help = command.help)
21+
command.configure_subparser(subparser)
22+
args = parser.parse_args()
23+
24+
# Find the extension that was called
25+
command = [x for x in self.commands if x.name == args.command][0]
26+
command.run(args)
27+
28+
def run_action(self, action):
29+
pass
30+
31+
32+
if __name__ == '__main__':
33+
PbSDKShell().main()
34+

pebble/PblBuildCommand.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import sh, os
2+
from PblCommand import PblCommand
3+
4+
class PblBuildCommand(PblCommand):
5+
name = 'build'
6+
help = 'Build your Pebble project'
7+
8+
def configure_subparser(self, parser):
9+
parser.add_argument('--sdk', help='Path to Pebble SDK (ie: ~/pebble-dev/PebbleSDK-2.X/)')
10+
11+
def run(self, args):
12+
waf_path = os.path.join(os.path.join(self.sdk_path(args), 'Pebble'), 'waf')
13+
print "Path to waf: {}".format(waf_path)
14+
os.system(waf_path + " configure build")
15+
16+
def sdk_path(self, args):
17+
"""
18+
Tries to guess the location of the Pebble SDK
19+
"""
20+
21+
if args.sdk:
22+
return args.sdk
23+
else:
24+
return os.path.normpath(os.path.join(os.path.dirname(__file__), os.path.join('..', '..', '..')))

pebble/PblCommand.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import os
2+
3+
class PblCommand:
4+
name = ''
5+
help = ''
6+
7+
def run(args):
8+
pass
9+
10+
def configure_subparser(self, parser):
11+
pass

pebble/PblProjectCreator.py

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import os, sh
2+
import uuid
3+
4+
from PblCommand import PblCommand
5+
6+
class PblProjectCreator(PblCommand):
7+
name = 'new-project'
8+
help = 'Create a new Pebble project'
9+
10+
def configure_subparser(self, parser):
11+
parser.add_argument("name", help = "Name of the project you want to create")
12+
13+
def run(self, args):
14+
print "Creating new project {}".format(args.name)
15+
16+
# User can give a path to a new project dir
17+
project_path = args.name
18+
project_name = os.path.split(project_path)[1]
19+
project_root = os.path.join(os.getcwd(), project_path)
20+
21+
project_resources_src = os.path.join(project_root, os.path.join("resources","src"))
22+
project_src = os.path.join(project_root, "src")
23+
24+
# Create directories
25+
os.makedirs(project_root)
26+
os.makedirs(project_resources_src)
27+
os.makedirs(project_src)
28+
29+
# Create main .c file
30+
self.generate_main_file(os.path.join(project_src, "%s.c" % (project_name)))
31+
32+
# Add resource file
33+
open(os.path.join(project_resources_src, "resource_map.json"), "w").write(FILE_DUMMY_RESOURCE_MAP)
34+
35+
# Add wscript file
36+
open(os.path.join(project_root, "wscript"), "w").write(FILE_WSCRIPT)
37+
38+
# Add .gitignore file
39+
open(os.path.join(project_root, ".gitignore"), "w").write(FILE_GITIGNORE)
40+
41+
def generate_uuid_as_array(self):
42+
"""
43+
Returns a freshly generated UUID value in string form formatted as
44+
a C array for inclusion in a template's "#define MY_UUID {...}"
45+
macro.
46+
"""
47+
return ", ".join(["0x%02X" % ord(b) for b in uuid.uuid4().bytes])
48+
49+
50+
def generate_main_file(self, destination_filepath):
51+
"""
52+
Generates the main file *and* replaces a dummy UUID
53+
value in it with a freshly generated value.
54+
"""
55+
56+
# This is the dummy UUID value in the template file.
57+
UUID_VALUE_TO_REPLACE="/* GENERATE YOURSELF USING `uuidgen` */ 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF"
58+
59+
open(destination_filepath, "w").write(FILE_DUMMY_MAIN.replace(UUID_VALUE_TO_REPLACE, self.generate_uuid_as_array(), 1))
60+
61+
62+
FILE_GITIGNORE = """
63+
# Ignore build generated files
64+
build
65+
"""
66+
67+
FILE_WSCRIPT = """
68+
#
69+
# This file is the default set of rules to compile a Pebble project.
70+
#
71+
# Feel free to customize this to your needs.
72+
#
73+
74+
top = '.'
75+
out = 'build'
76+
77+
def options(ctx):
78+
ctx.load('pebble_sdk')
79+
80+
def configure(ctx):
81+
ctx.load('pebble_sdk')
82+
83+
def build(ctx):
84+
ctx.load('pebble_sdk')
85+
"""
86+
87+
# When an empty resource map is required this can be used but...
88+
FILE_DEFAULT_RESOURCE_MAP = """
89+
{"friendlyVersion": "VERSION", "versionDefName": "VERSION", "media": []}
90+
"""
91+
92+
# ...for the moment we need to have one with a dummy entry due to
93+
# a bug that causes a hang when there's an empty resource map.
94+
FILE_DUMMY_RESOURCE_MAP = """
95+
{"friendlyVersion": "VERSION",
96+
"versionDefName": "VERSION",
97+
"media": [
98+
{
99+
"type":"raw",
100+
"defName":"DUMMY",
101+
"file":"resource_map.json"
102+
}
103+
]
104+
}
105+
"""
106+
107+
FILE_DUMMY_MAIN = """#include <pebble_os.h>
108+
#include <pebble_app.h>
109+
#include <pebble_fonts.h>
110+
111+
112+
#define MY_UUID { /* GENERATE YOURSELF USING `uuidgen` */ 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF, 0xBE, 0xEF }
113+
PBL_APP_INFO(MY_UUID,
114+
"Template App", "Your Company",
115+
1, 0, /* App version */
116+
DEFAULT_MENU_ICON,
117+
APP_INFO_STANDARD_APP);
118+
119+
Window *window;
120+
TextLayer *text_layer;
121+
122+
void select_click_handler(ClickRecognizerRef recognizer, void *context) {
123+
text_layer_set_text(text_layer, "Select");
124+
}
125+
126+
void up_click_handler(ClickRecognizerRef recognizer, void *context) {
127+
text_layer_set_text(text_layer, "Up");
128+
}
129+
130+
void down_click_handler(ClickRecognizerRef recognizer, void *context) {
131+
text_layer_set_text(text_layer, "Button");
132+
}
133+
134+
void config_provider(ClickConfig **config, Window *window) {
135+
config[BUTTON_ID_SELECT]->click.handler = select_click_handler;
136+
config[BUTTON_ID_UP]->click.handler = up_click_handler;
137+
config[BUTTON_ID_DOWN]->click.handler = down_click_handler;
138+
}
139+
140+
void handle_init() {
141+
window = window_create();
142+
window_stack_push(window, true /* Animated */);
143+
144+
window_set_click_config_provider(window, (ClickConfigProvider) config_provider);
145+
146+
text_layer = text_layer_create(GRect(/* x: */ 0, /* y: */ 74,
147+
/* width: */ 144, /* height: */ 20));
148+
layer_add_child(window_get_root_layer(window), text_layer_get_layer(text_layer));
149+
150+
text_layer_set_text(text_layer, "Press a button");
151+
}
152+
153+
void handle_deinit() {
154+
// unsubscribe from services here
155+
}
156+
157+
void pbl_main(void *params) {
158+
register_init_handler(&handle_init);
159+
register_deinit_handler(&handle_deinit);
160+
app_event_loop();
161+
}
162+
"""

0 commit comments

Comments
 (0)