HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

DuckyScript precompiler for Arduino Leonardo

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arduinoleonardoduckyscriptprecompilerfor

Problem

I've made a python program to convert DuckyScript code to Arduino code for Leonardo boards. Below you can find both the project files and a sample script.

compiler.py (the program base):

```
#!/usr/bin/env python3

"""
Usage: {}

should be a DuckieScript file and will be an Arduino sketch
"""

import os
import sys
import fileinput
import textwrap
from data import keycodes
from data import code

delay = 0
cmdtype = 0
commands = ""
includes = ""
defines = ""
loop = ""

def info(type, msg, **kwargs):
lineno = fileinput.lineno()
path = os.path.basename(input_file)
exit = kwargs.get('exit', None)
types = ['error', 'warning', 'info', 'screw up risk']
message = '{}:{}: {}: {}'.format(path, lineno, types[type], msg)
print(message)
if exit:
print('{}: compilation aborted.'.format(path))
sys.exit(exit)

def getkey(keys):
global commands
keys = keys.split()
normalkey = list()
modifiers = 0
for key in keys:
if not key.isupper():
key = key.upper()
if len(key) is not 1:
info(1, 'you should type all the special keys in uppercase')

try:
key = [keycodes.get(code) for code in keycodes if key in code][0]
except IndexError:
info(0, 'unrecognized key: {}'.format(key), exit=127)

if key[1]:
modifiers |= key[0]
else:
normalkey.append(key[0])

if len(normalkey) > 6:
info(0, 'you can\'t press more than 6 keys at the same time', exit=126)

arguments = [0] * 7
arguments[6] = modifiers
for number, argument in enumerate(normalkey):
arguments[number] = argument
arguments = [format(byte, '#04x') for byte in arguments]
commands += 'sendKey({},{},{},{},{},{},{});'.format(*arguments)
commands += '\n'

return True

if len(sys.argv) is not 3:
print(__doc__.format(sys.argv[0]))
sys.exit(1)
elif not os.path.isfile(sys.argv[1]):
print()
print('

Solution

Globals...

You freely modify

delay = 0
cmdtype = 0
commands = ""
includes = ""
defines = ""
loop = ""


from anywhere, this can get real hard to keep track of, pass things as arguments and return instead.

Use multiline strings

commands += 'int i=0;'
    commands += '\n'
    commands += 'for(i; i<={}; i++) {{'.format(options)
    commands += '\n'
    commands += '  {}'.format(last_command)
    commands += '\n'
    commands += '  delay({});'.format(delay)
    commands += '\n'
    commands += '}'
    commands += '\n'


Becomes:

commands = """\
int i = 0

for(i; ...
...

""".format(options, last_command, delay)


The benefit in readability is clear.

Code Snippets

delay = 0
cmdtype = 0
commands = ""
includes = ""
defines = ""
loop = ""
commands += 'int i=0;'
    commands += '\n'
    commands += 'for(i; i<={}; i++) {{'.format(options)
    commands += '\n'
    commands += '  {}'.format(last_command)
    commands += '\n'
    commands += '  delay({});'.format(delay)
    commands += '\n'
    commands += '}'
    commands += '\n'
commands = """\
int i = 0

for(i; ...
...

""".format(options, last_command, delay)

Context

StackExchange Code Review Q#108174, answer score: 2

Revisions (0)

No revisions yet.