- Added syntax check unit-test - Added none emitter (for syntax validation check) - Added KLL 0.5c example expressions - Added Travis-CI test for syntax check - Cleaned up READMEdev
env: | env: | ||||
# Basic KLL Tests | # Basic KLL Tests | ||||
- DIR=tests SCRIPT=sanity.bash | - DIR=tests SCRIPT=sanity.bash | ||||
- DIR=tests SCRIPT=syntax.bash | |||||
# Exclusions | # Exclusions | ||||
matrix: | matrix: |
KLL Compiler | KLL Compiler | ||||
------------ | ------------ | ||||
Most current version of the [KLL Spec](http://input.club/kll). | |||||
Most current version of the [KLL Spec](https://github.com/kiibohd/kll-spec). | |||||
Uses [funcparserlib](https://code.google.com/p/funcparserlib/) | Uses [funcparserlib](https://code.google.com/p/funcparserlib/) | ||||
### General Usage | ### General Usage | ||||
```bash | ```bash | ||||
kll.py <kll files> | |||||
kll <kll files> | |||||
``` | ``` | ||||
### Kiibohd Controller Usage | ### Kiibohd Controller Usage | ||||
```bash | ```bash | ||||
kll.py <basemap kll files> --default <default layer kll files> --partial <partial layer 1 kll files> --partial <partial layer 2 kll files> --backend kiibohd --templates templates/kiibohdKeymap.h templates/kiibohdDefs.h --outputs generatedKeymap.h kll_defs.h | |||||
kll.py <misc kll files> --config <config/capability kll files> --base <basemap kll files) --default <default layer kll files> --partial <partial layer 1 kll files> --partial <partial layer 2 kll files> | |||||
``` | ``` | ||||
See `kll.py --help` for the most up to date documentation | |||||
See `kll --help` for the most up to date documentation | |||||
Unit Tests | |||||
---------- | |||||
Unit tests can be found in the [tests](tests) directory. | |||||
They are run by Travis-CI, but can be useful when testing your own changes. | |||||
Remember to add new tests when adding new features/changes. | |||||
Patches/Features/Backends | Patches/Features/Backends |
# TODO Detect whether colorization should be used | # TODO Detect whether colorization should be used | ||||
self.color = self.color in ['auto', 'always'] | self.color = self.color in ['auto', 'always'] | ||||
# Validate if it's a valid emitter | |||||
if self.emitter not in self.emitters.emitter_list(): | |||||
print( "{0} Invalid emitter '{1}'".format( ERROR, self.emitter ) ) | |||||
print( "Valid emitters: {0}".format( self.emitters.emitter_list() ) ) | |||||
sys.exit( 2 ) | |||||
def command_line_flags( self, parser ): | def command_line_flags( self, parser ): | ||||
''' | ''' | ||||
Group parser for command line options | Group parser for command line options | ||||
( 'PixelLayerStart', ( r'PL\[', ) ), | ( 'PixelLayerStart', ( r'PL\[', ) ), | ||||
( 'Animation', ( r'A"[^"]+"', ) ), | ( 'Animation', ( r'A"[^"]+"', ) ), | ||||
( 'AnimationStart', ( r'A\[', ) ), | ( 'AnimationStart', ( r'A\[', ) ), | ||||
( 'USBCode', ( r'U(("[^"]+")|(0x[0-9a-fA-F]+)|([0-9]+))', ) ), | |||||
( 'USBCodeStart', ( r'U\[', ) ), | |||||
( 'ScanCode', ( r'S((0x[0-9a-fA-F]+)|([0-9]+))', ) ), | |||||
( 'ScanCodeStart', ( r'S\[', ) ), | |||||
( 'CodeBegin', ( r'\[', ) ), | ( 'CodeBegin', ( r'\[', ) ), | ||||
( 'CodeEnd', ( r'\]', ) ), | ( 'CodeEnd', ( r'\]', ) ), | ||||
( 'Position', ( r'r?[xyz]:[0-9]+(.[0-9]+)?', ) ), | ( 'Position', ( r'r?[xyz]:[0-9]+(.[0-9]+)?', ) ), | ||||
( 'PixelOperator', ( r'(\+:|-:|>>|<<)', ) ), | ( 'PixelOperator', ( r'(\+:|-:|>>|<<)', ) ), | ||||
( 'String', ( r'"[^"]*"', ) ), | |||||
( 'Operator', ( r':', ) ), | ( 'Operator', ( r':', ) ), | ||||
( 'Comma', ( r',', ) ), | ( 'Comma', ( r',', ) ), | ||||
( 'Dash', ( r'-', ) ), | ( 'Dash', ( r'-', ) ), | ||||
( 'Plus', ( r'\+', ) ), | ( 'Plus', ( r'\+', ) ), | ||||
( 'Parenthesis', ( r'\(|\)', ) ), | ( 'Parenthesis', ( r'\(|\)', ) ), | ||||
( 'Percent', ( r'0|([1-9][0-9]*)%', ) ), | |||||
( 'Number', ( r'-?(0x[0-9a-fA-F]+)|(0|([1-9][0-9]*))', ) ), | ( 'Number', ( r'-?(0x[0-9a-fA-F]+)|(0|([1-9][0-9]*))', ) ), | ||||
( 'Name', ( r'[A-Za-z_][A-Za-z_0-9]*', ) ), | ( 'Name', ( r'[A-Za-z_][A-Za-z_0-9]*', ) ), | ||||
] | ] |
### Imports ### | ### Imports ### | ||||
import emitters.kiibohd.kiibohd as kiibohd | import emitters.kiibohd.kiibohd as kiibohd | ||||
import emitters.none.none as none | |||||
# Dictionary of Emitters | # Dictionary of Emitters | ||||
self.emitters = { | self.emitters = { | ||||
'kiibohd' : kiibohd.Kiibohd( control ) | |||||
'kiibohd' : kiibohd.Kiibohd( control ), | |||||
'none' : none.Drop( control ) | |||||
} | } | ||||
def emitter_default( self ): | def emitter_default( self ): |
#!/usr/bin/env python3 | |||||
''' | |||||
KLL Data Dropper (Doesn't emit anything) | |||||
''' | |||||
# Copyright (C) 2016 by Jacob Alexander | |||||
# | |||||
# This file is free software: you can redistribute it and/or modify | |||||
# it under the terms of the GNU General Public License as published by | |||||
# the Free Software Foundation, either version 3 of the License, or | |||||
# (at your option) any later version. | |||||
# | |||||
# This file is distributed in the hope that it will be useful, | |||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
# GNU General Public License for more details. | |||||
# | |||||
# You should have received a copy of the GNU General Public License | |||||
# along with this file. If not, see <http://www.gnu.org/licenses/>. | |||||
### Imports ### | |||||
from common.emitter import Emitter | |||||
### Decorators ### | |||||
## Print Decorator Variables | |||||
ERROR = '\033[5;1;31mERROR\033[0m:' | |||||
WARNING = '\033[5;1;33mWARNING\033[0m:' | |||||
### Classes ### | |||||
class Drop( Emitter ): | |||||
''' | |||||
Doesn't emit at all, just ignores everything | |||||
''' | |||||
def __init__( self, control ): | |||||
''' | |||||
Emitter initialization | |||||
@param control: ControlStage object, used to access data from other stages | |||||
''' | |||||
Emitter.__init__( self, control ) | |||||
def command_line_args( self, args ): | |||||
''' | |||||
Group parser for command line arguments | |||||
@param args: Name space of processed arguments | |||||
''' | |||||
def command_line_flags( self, parser ): | |||||
''' | |||||
Group parser for command line options | |||||
@param parser: argparse setup object | |||||
''' | |||||
def output( self ): | |||||
''' | |||||
Final Stage of Emitter | |||||
Nothing to do | |||||
''' | |||||
def process( self ): | |||||
''' | |||||
Emitter Processing | |||||
Nothing to do, just dropping all the results | |||||
''' | |||||
A[BLEEdsing2, 0] <= PL[0](127, 30, 40), P[5](20, 30, 40); | A[BLEEdsing2, 0] <= PL[0](127, 30, 40), P[5](20, 30, 40); | ||||
A[BLEEdsing2, 1] <= P[1-20,40](40,50,0x60); | A[BLEEdsing2, 1] <= P[1-20,40](40,50,0x60); | ||||
A[BLEEdsing2, 2] <= P[c:0](40,50,0x60); | |||||
A[BLEEdsing2, 3] <= P[c:10%](40,50,0x60); | |||||
A[BLEEdsing2, 4] <= P[r:10%,c:20](40,50,0x60); | |||||
A[BLEEdsing2, 5] <= P[r:i+10%,c:i-20](40,50,0x60); | |||||
A[BLEEdsing2, 6] <= P[r:i+10%](40,50,0x60); | |||||
A[BLEEdsing2, 7] <= U["A"](40,50,0x60); | |||||
A[BLEEdsing2, 8] <= U"B"(40,50,0x60); | |||||
A[BLEEdsing2, 9] <= S120(40,50,0x60); | |||||
A[BLEEdsing2, 10] <= S[0x10](40,50,0x60); | |||||
# Animation Triggers | # Animation Triggers | ||||
myCapability => myFunc( myArg1 : 1, myArg2 : 4 ); | myCapability => myFunc( myArg1 : 1, myArg2 : 4 ); |
parser = argparse.ArgumentParser( | parser = argparse.ArgumentParser( | ||||
usage="%(prog)s [options..] [<generic>..]", | usage="%(prog)s [options..] [<generic>..]", | ||||
description="KLL Compiler - Generates specified output from KLL .kll files.", | description="KLL Compiler - Generates specified output from KLL .kll files.", | ||||
epilog="Example: {0} TODO".format( os.path.basename( sys.argv[0] ) ), | |||||
epilog="Example: {0} scan_map.kll".format( os.path.basename( sys.argv[0] ) ), | |||||
formatter_class=argparse.RawTextHelpFormatter, | formatter_class=argparse.RawTextHelpFormatter, | ||||
add_help=False, | add_help=False, | ||||
) | ) |
#!/bin/bash | |||||
# Common functions for running kll unit tests | |||||
# Jacob Alexander 2016 | |||||
PASSED=0 | |||||
FAILED=0 | |||||
# Results | |||||
result() { | |||||
echo "--- Results ---" | |||||
echo "${PASSED}/$((PASSED+FAILED))" | |||||
if (( FAILED == 0 )); then | |||||
return 0 | |||||
else | |||||
return 1 | |||||
fi | |||||
} | |||||
# Runs a command, increments test passed/failed | |||||
# Args: Command | |||||
cmd() { | |||||
# Run command | |||||
echo "CMD: $@" | |||||
$@ | |||||
local RET=$? | |||||
# Check command | |||||
if [[ ${RET} -ne 0 ]]; then | |||||
((FAILED++)) | |||||
else | |||||
((PASSED++)) | |||||
fi | |||||
return ${RET} | |||||
} | |||||
# Run a command multiple times using an array of values | |||||
# Arg #1: Base command | |||||
# Arg #2: Static arguments | |||||
# Arg #3: Static arguments to call when command fails (debug info) | |||||
# Arg #4+: Array of variations to swap into the command | |||||
cmds() { | |||||
local BASE=${1} | |||||
shift | |||||
local STATIC=${1} | |||||
shift | |||||
local FAIL_STATIC=${1} | |||||
shift | |||||
local VARS=${@} # Rest of arguments | |||||
# Base command | |||||
echo "BASE CMD: ${BASE} ${STATIC}" | |||||
# Iterate over variations | |||||
for var in ${VARS[@]}; do | |||||
cmd ${BASE} ${STATIC} ${var} | |||||
if [[ $? -ne 0 ]]; then | |||||
echo "CMD FAILED - RUNNING DEBUG ARGS - ${BASE} ${FAIL_STATIC} ${var}" | |||||
${BASE} ${FAIL_STATIC} ${var} | |||||
fi | |||||
done | |||||
} | |||||
#!/bin/bash | #!/bin/bash | ||||
# Basic sanity check for kll compiler | # Basic sanity check for kll compiler | ||||
# Currently runs both versions of the compiler | # Currently runs both versions of the compiler | ||||
set +x | |||||
# Jacob Alexander 2016 | |||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||||
PASSED=0 | |||||
FAILED=0 | |||||
# Results | |||||
result() { | |||||
echo "--- Results ---" | |||||
echo "${PASSED}/$((PASSED+FAILED))" | |||||
if (( FAILED == 0 )); then | |||||
return 0 | |||||
else | |||||
return 1 | |||||
fi | |||||
} | |||||
# Runs a command, increments test passed/failed | |||||
# Args: Command | |||||
cmd() { | |||||
# Run command | |||||
echo "CMD: $@" | |||||
$@ | |||||
# Check command | |||||
if [[ $? -ne 0 ]]; then | |||||
((FAILED++)) | |||||
else | |||||
((PASSED++)) | |||||
fi | |||||
} | |||||
# Common functions | |||||
source ${SCRIPT_DIR}/common.bash | |||||
# Start in kll top-level directory | # Start in kll top-level directory | ||||
cd ${SCRIPT_DIR}/.. | cd ${SCRIPT_DIR}/.. | ||||
## Tests | |||||
cmd ./kll.py --version | cmd ./kll.py --version | ||||
cmd ./kll --version | cmd ./kll --version | ||||
## Tests complete | |||||
result | result | ||||
exit $? | exit $? | ||||
#!/bin/bash | |||||
# Use example .kll files to check syntax compatibility | |||||
# Does not generate code, so resulting datastructures do not necessarily need to functino | |||||
# Jacob Alexander 2016 | |||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |||||
# Common functions | |||||
source ${SCRIPT_DIR}/common.bash | |||||
# Start in kll top-level directory | |||||
cd ${SCRIPT_DIR}/.. | |||||
# Args used for each of the tests | |||||
ARGS="--emitter none --data-finalization-display" | |||||
FAIL_ARGS="--emitter none --token-debug --parser-token-debug --operation-organization-display --data-organization-display --data-finalization-display" | |||||
# Files to check syntax on | |||||
FILES=( | |||||
examples/assignment.kll | |||||
examples/capabilitiesExample.kll | |||||
examples/colemak.kll | |||||
examples/defaultMapExample.kll | |||||
examples/example.kll | |||||
examples/hhkbpro2.kll | |||||
examples/leds.kll | |||||
examples/mapping.kll | |||||
examples/md1Map.kll | |||||
examples/simple1.kll | |||||
examples/simple2.kll | |||||
examples/simpleExample.kll | |||||
examples/state_scheduling.kll | |||||
) | |||||
## Tests | |||||
cmds "./kll" "${ARGS}" "${FAIL_ARGS}" ${FILES[@]} | |||||
## Tests complete | |||||
result | |||||
exit $? | |||||