11#!/usr/bin/env python
2+ """
3+ Arduino-mk Makefile and project initialiser
4+
5+ This script can be used in it's basic form create a project specific Makefile
6+ for use with Arduino-mk. Addionally, it can be used to create a template
7+ Arduino source file and a traditional boilerplate project file structure.
8+
9+ Example:
10+ * Run prompted within current working directory: `ardmk-init`
11+ * Create Arduino Uno Makefile (useful within a library example): `ardmk-init -qb uno`
12+ * Create boilerplate Arduino Uno project in current working directory of same
13+ name: `ardmk-init -b uno --quiet --project`
14+ * Create Arduino-mk nano Makefile in current working directory with template .ino:
15+ `ardmk-init -b nano -u atmega328 -qtn my-project`
16+
17+ See `armk-init --help` for CLI arguments
18+ """
219
320from __future__ import print_function
4- import serial
521import os
622import argparse
723from clint .textui import prompt , validators , colored , puts
824
925## Global Vars
1026VERSION = "1.0"
11- directory = os .getcwd ()
12- ard_template = "\n \
27+ ARD_TEMPLATE = "\n \
1328 #include <Arduino.h>\n \
1429 #include <Wire.h>\n \
1530\n \
@@ -22,53 +37,63 @@ void loop() {\n\
2237 "
2338
2439## Command Parser
25- parser = argparse .ArgumentParser (description = 'Arduino Makefile and boilerplate project generator. For use with Ard-Makefile: https://github.com/sudar/Arduino-Makefile. Script created by John Whittington https://github.com/tuna-f1sh 2017\n \n Version: ' + VERSION , usage = '"ardmk-init -b uno -quiet -project" Automonously create boiler plate Arduino Uno project in current working directory with same name. See --help for more.' )
26- parser .add_argument ('-v' , '--verbose' , action = 'store_true' , help = "print file contents during creation" )
27- parser .add_argument ('-d' , '--directory' , default = directory , help = 'directory to run generator' )
28- parser .add_argument ('-b' , '--board' , default = 'uno' , help = 'board tag' )
29- parser .add_argument ('-u' , '--micro' , default = 'AUTO' , help = 'microcontroller on board' )
30- parser .add_argument ('-f' , '--freq' , default = 'AUTO' , help = 'mlock frequency' )
31- parser .add_argument ('-p' , '--port' , default = 'AUTO' , help = 'monitor port' )
32- parser .add_argument ('-n' , '--name' , default = os .path .basename (directory ), help = 'project name' )
33- parser .add_argument ('-q' , '--quiet' , action = 'store_true' , help = 'run quiet without user prompts' )
34- parser .add_argument ('-P' , '--project' , action = 'store_true' , help = 'create boilerplate project with src, lib and bin folder structure' )
35- parser .add_argument ('-t' , '--template' , action = 'store_true' , help = 'create bare minimum Arduino source file' )
36- args = parser .parse_args ()
37-
38- directory = args .directory
39-
40- def generateMakefile ():
40+ PARSER = argparse .ArgumentParser (description = 'Arduino Makefile and boilerplate project generator.\
41+ For use with Ard-Makefile: https://github.com/sudar/Arduino-Makefile.\
42+ Script created by John Whittington https://github.com/tuna-f1sh 2017\
43+ \n \n Version: ' + VERSION , usage = 'ardmk-init # prompted CLI, see --help for more.' )
44+ PARSER .add_argument ('-v' , '--verbose' , action = 'store_true' ,
45+ help = "print file contents during creation" )
46+ PARSER .add_argument ('-d' , '--directory' , default = os .getcwd (), help = 'directory to run generator' )
47+ PARSER .add_argument ('-b' , '--board' , default = 'uno' , help = 'board tag' )
48+ PARSER .add_argument ('-u' , '--micro' , default = 'AUTO' , help = 'microcontroller on board' )
49+ PARSER .add_argument ('-f' , '--freq' , default = 'AUTO' , help = 'mlock frequency' )
50+ PARSER .add_argument ('-p' , '--port' , default = 'AUTO' , help = 'monitor port' )
51+ PARSER .add_argument ('-n' , '--name' , default = os .path .basename (os .getcwd ()), help = 'project name' )
52+ PARSER .add_argument ('-q' , '--quiet' , action = 'store_true' , help = 'run quiet without user prompts' )
53+ PARSER .add_argument ('-P' , '--project' , action = 'store_true' ,
54+ help = 'create boilerplate project with src, lib and bin folder structure' )
55+ PARSER .add_argument ('-t' , '--template' , action = 'store_true' ,
56+ help = 'create bare minimum Arduino source file' )
57+ ARGS = PARSER .parse_args ()
58+
59+ def generate_makefile ():
60+ """
61+ Generate the Makefile content using prompts or parsed arguments
62+ """
4163 # Header
42- fileContents = "# Generated by ard-make version " + VERSION + "\n \n "
64+ file_content = "# Generated by ard-make version " + VERSION + "\n \n "
4365
4466 # Basic
45- if not args .quiet :
46- puts (colored .cyan ("Generating Arduino Ard-Makefile project in " + os .path .abspath (directory )))
67+ if not ARGS .quiet :
68+ puts (colored .cyan ("Generating Arduino Ard-Makefile project in "
69+ + os .path .abspath (ARGS .directory )))
4770 btag = prompt .query ('Board tag?' , default = 'uno' )
48- if not btag = = 'uno' :
71+ if btag ! = 'uno' :
4972 bsub = prompt .query ('Board sub micro?' , default = 'atmega328' )
5073 f_cpu = prompt .query ('Board frequency' , default = '16000000L' )
5174 else :
5275 bsub = 'AUTO'
5376 f_cpu = 'AUTO'
5477 monitor_port = prompt .query ('Arduino port?' , default = 'AUTO' )
5578 else :
56- btag = args .board
57- bsub = args .micro
58- f_cpu = args .freq
59- monitor_port = args .port
79+ btag = ARGS .board
80+ bsub = ARGS .micro
81+ f_cpu = ARGS .freq
82+ monitor_port = ARGS .port
6083
61- fileContents += checkDefine ('BOARD_TAG' , btag )
62- fileContents += checkDefine ('BOARD_SUB' , bsub )
63- fileContents += checkDefine ('F_CPU' , f_cpu )
64- fileContents += checkDefine ('MONITOR_PORT' , monitor_port )
84+ file_content += check_define ('BOARD_TAG' , btag )
85+ file_content += check_define ('BOARD_SUB' , bsub )
86+ file_content += check_define ('F_CPU' , f_cpu )
87+ file_content += check_define ('MONITOR_PORT' , monitor_port )
6588
6689 # Extended
67- if not args .quiet :
90+ if not ARGS .quiet :
6891 if not prompt .yn ('Extended options?' , default = 'n' ):
6992 if not prompt .yn ('Define local folders?' , default = 'n' ):
70- src_dir = prompt .query ('Sources folder (Makefile will be created here)?' , default = '' , validators = [])
71- userlibs = prompt .query ('Library folder (will create if does not exist) - AUTO is Sketchbook directory?' , default = 'AUTO' , validators = [])
93+ src_dir = prompt .query ('Sources folder (Makefile will be created here)?' ,\
94+ default = '' , validators = [])
95+ userlibs = prompt .query ('Library folder (will create if does not exist) - AUTO is Sketchbook directory?' ,
96+ default = 'AUTO' , validators = [])
7297 obj_dir = prompt .query ('Output directory?' , default = 'AUTO' , validators = [])
7398 else :
7499 src_dir = ''
@@ -78,37 +103,38 @@ def generateMakefile():
78103 isp_prog = prompt .query ('ISP programmer?' , default = 'atmelice_isp' )
79104 isp_port = prompt .query ('ISP port?' , default = 'AUTO' )
80105 if not prompt .yn ('Quiet make?' , default = 'n' ):
81- fileContents += "ARDUINO_QUIET = 1\n "
106+ file_content += "ARDUINO_QUIET = 1\n "
82107
83- fileContents += checkDefine ('ISP_PROG' , isp_prog )
84- fileContents += checkDefine ('ISP_PORT' , isp_port )
85- fileContents += checkDefine ('BOARDS_TXT' , boards_txt )
108+ file_content += check_define ('ISP_PROG' , isp_prog )
109+ file_content += check_define ('ISP_PORT' , isp_port )
110+ file_content += check_define ('BOARDS_TXT' , boards_txt )
86111
87112 # Check andd create folders
88- checkCreateFolder (src_dir )
89- checkCreateFolder (userlibs )
90- checkCreateFolder (obj_dir )
113+ check_create_folder (src_dir )
114+ check_create_folder (userlibs )
115+ check_create_folder (obj_dir )
91116
92117 # Makefile will be in src_dir so lib and bin must be relative
93118 if src_dir :
94119 userlibs = "../" + userlibs
95120 obj_dir = "../" + obj_dir
96121
97- fileContents += checkDefine ('USER_LIB_PATH' , userlibs )
98- fileContents += checkDefine ('OBJDIR' , obj_dir )
122+ file_content += check_define ('USER_LIB_PATH' , userlibs )
123+ file_content += check_define ('OBJDIR' , obj_dir )
99124 else :
100125 src_dir = ''
101126
102- if args .template or not prompt .yn ('Create template Arduino source?' , default = 'n' ):
103- sourceFilename = prompt .query ('Name of project?' , default = os .path .basename (os .getcwd ()))
127+ if ARGS .template or not prompt .yn ('Create template Arduino source?' , default = 'n' ):
128+ source_filename = prompt .query ('Name of project?' ,
129+ default = os .path .basename (os .getcwd ()))
104130 if src_dir :
105- writeTemplate (src_dir + "/" + sourceFilename )
131+ write_template (src_dir + "/" + source_filename )
106132 else :
107- writeTemplate ( sourceFilename )
108- fileContents += checkDefine ('TARGET' , sourceFilename )
133+ write_template ( source_filename )
134+ file_content += check_define ('TARGET' , source_filename )
109135
110136 else :
111- if args .project :
137+ if ARGS .project :
112138 src_dir = 'src'
113139 userlibs = 'lib'
114140 obj_dir = 'bin'
@@ -118,89 +144,111 @@ def generateMakefile():
118144 obj_dir = 'AUTO'
119145
120146 # Check andd create folders
121- checkCreateFolder (src_dir )
122- checkCreateFolder (userlibs )
123- checkCreateFolder (obj_dir )
147+ check_create_folder (src_dir )
148+ check_create_folder (userlibs )
149+ check_create_folder (obj_dir )
124150
125151 # Makefile will be in src_dir so lib and bin must be relative
126152 if src_dir :
127153 userlibs = "../" + userlibs
128154 obj_dir = "../" + obj_dir
129155
130- fileContents += checkDefine ('USER_LIB_PATH' , userlibs )
131- fileContents += checkDefine ('OBJDIR' , obj_dir )
156+ file_content += check_define ('USER_LIB_PATH' , userlibs )
157+ file_content += check_define ('OBJDIR' , obj_dir )
132158
133- if args .project or args .template :
159+ if ARGS .project or ARGS .template :
134160 if src_dir :
135- writeTemplate (src_dir + "/" + args .name )
161+ write_template (src_dir + "/" + ARGS .name )
136162 else :
137- writeTemplate ( args .name )
138- fileContents += checkDefine ('TARGET' , args .name )
163+ write_template ( ARGS .name )
164+ file_content += check_define ('TARGET' , ARGS .name )
139165
140166 if not "ARDMK_DIR" in os .environ :
141- if args .quiet :
142- puts (colored .magenta ('Warning: ARDMK_DIR environment variable not defined. Must be defined for Makefile to work' ))
167+ if ARGS .quiet :
168+ puts (colored .magenta ('Warning: ARDMK_DIR environment variable not defined. \
169+ Must be defined for Makefile to work' ))
143170 else :
144- ardmk = prompt .query ('Arduino Makefile path?' , default = '/usr/share/arduino' , validators = [validators .PathValidator ()])
171+ ardmk = prompt .query ('Arduino Makefile path?' ,
172+ default = '/usr/share/arduino' ,
173+ validators = [validators .PathValidator ()])
145174 ardmk = "ARDMK_DIR := " + ardmk + "\n "
146175
147- fileContents += "\n include $(ARDMK_DIR)/Arduino.mk"
176+ file_content += "\n include $(ARDMK_DIR)/Arduino.mk"
148177
149178 # Add forward slash if source directory exists
150179 if src_dir :
151- writeToMakefile ( fileContents , (src_dir + "/" ))
180+ write_to_makefile ( file_content , (src_dir + "/" ))
152181 else :
153- writeToMakefile ( fileContents , "" )
182+ write_to_makefile ( file_content , "" )
154183
155- return fileContents
184+ return file_content
156185
157- def writeToMakefile (fileContents , path ):
186+ def write_to_makefile (file_content , path ):
187+ """
188+ Write the Makefile file
189+ """
158190 makefile = open (path + "Makefile" , 'w' )
159191 puts (colored .cyan ("Writing Makefile..." ))
160- if args .verbose :
161- puts (colored .yellow (fileContents ))
162- makefile .write (fileContents )
192+ if ARGS .verbose :
193+ puts (colored .yellow (file_content ))
194+ makefile .write (file_content )
163195 makefile .close ()
164196
165- def writeTemplate (filename ):
197+ def write_template (filename ):
198+ """
199+ Write template Arduino .ino source
200+ """
166201 puts (colored .cyan ("Writing " + os .path .abspath (filename ) + ".ino..." ))
167202 if os .path .isfile (filename + '.ino' ):
168- if args .quiet :
203+ if ARGS .quiet :
169204 puts (colored .red (filename + '.ino' + ' already exists! Stopping.' ))
170205 return
171206 puts (colored .red (filename + '.ino' + ' already exists! Overwrite?' ))
172207 if prompt .yn ('Continue?' , default = 'n' ):
173208 return
174- src = open ((filename + ".ino" ),'w' )
175- if args .verbose :
176- puts (colored .yellow (ard_template ))
177- src .write ("/* Project: " + filename + " */\n " + ard_template )
209+ src = open ((filename + ".ino" ), 'w' )
210+ if ARGS .verbose :
211+ puts (colored .yellow (ARD_TEMPLATE ))
212+ src .write ("/* Project: " + filename + " */\n " + ARD_TEMPLATE )
178213 src .close ()
179214
180- def checkCreateFolder (folder ):
215+ def check_create_folder (folder ):
216+ """
217+ Check if folder exists and make it if it doesn't and hasn't been set to AUTO
218+ """
181219 if folder and not folder == 'AUTO' :
182220 if not os .path .exists (folder ):
183221 puts (colored .cyan (("Creating " + os .path .abspath (folder ) + " folder" )))
184222 os .makedirs (folder )
185223
186- def checkDefine (define , user ):
224+ def check_define (define , user ):
225+ """
226+ Check whether user has set define and return Makefile formatted string if they have
227+ """
228+ # Return is empty unless user has passed value
229+ string = ""
230+
231+ # Set define only if not empty or set to AUTO
187232 if user and not user == 'AUTO' :
188- return define + " = " + user + "\n "
189- else :
190- return ""
233+ string = define + " = " + user + "\n "
191234
192- def main ():
235+ return string
236+
237+ if __name__ == '__main__' :
193238 # Create directory if not exist
194- checkCreateFolder ( directory )
239+ check_create_folder ( ARGS . directory )
195240 # Change to dir so all commands are run relative
196- os .chdir (directory )
241+ os .chdir (ARGS . directory )
197242 if os .path .isfile ('Makefile' ):
198- if args .quiet :
199- puts (colored .red ('Makefile in ' + os .path .abspath (directory ) + ' already exists! Stopping.' ))
200- return
201- puts (colored .red ('Makefile in ' + os .path .abspath (directory ) + ' already exists! Overwrite?' ))
243+ if ARGS .quiet :
244+ puts (colored .red ('Makefile in ' + os .path .abspath (ARGS .directory )
245+ + ' already exists! Stopping.' ))
246+ quit ()
247+
248+ # Confirm with user if not quiet mode
249+ puts (colored .red ('Makefile in ' + os .path .abspath (ARGS .directory )
250+ + ' already exists! Overwrite?' ))
202251 if prompt .yn ('Continue?' , default = 'n' ):
203- return
204- generateMakefile ();
205-
206- main ()
252+ quit ()
253+ # Run it
254+ generate_makefile ()
0 commit comments