Kaleidoscope Style Guide conformance

Signed-off-by: Gergely Nagy <algernon@madhouse-project.org>
pull/389/head
Gergely Nagy 8 years ago
parent bbc7ddaeff
commit 6839c3ca36

@ -5,9 +5,9 @@
[travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-Leader.svg?branch=master [travis:image]: https://travis-ci.org/keyboardio/Kaleidoscope-Leader.svg?branch=master
[travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-Leader [travis:status]: https://travis-ci.org/keyboardio/Kaleidoscope-Leader
[st:stable]: https://img.shields.io/badge/stable-✔-black.png?style=flat&colorA=44cc11&colorB=494e52 [st:stable]: https://img.shields.io/badge/stable-✔-black.svg?style=flat&colorA=44cc11&colorB=494e52
[st:broken]: https://img.shields.io/badge/broken-X-black.png?style=flat&colorA=e05d44&colorB=494e52 [st:broken]: https://img.shields.io/badge/broken-X-black.svg?style=flat&colorA=e05d44&colorB=494e52
[st:experimental]: https://img.shields.io/badge/experimental----black.png?style=flat&colorA=dfb317&colorB=494e52 [st:experimental]: https://img.shields.io/badge/experimental----black.svg?style=flat&colorA=dfb317&colorB=494e52
Leader keys are a kind of key where when they are tapped, all following keys are Leader keys are a kind of key where when they are tapped, all following keys are
swallowed, until the plugin finds a matching sequence in the dictionary, it swallowed, until the plugin finds a matching sequence in the dictionary, it
@ -40,27 +40,26 @@ dictionary:
#include <Kaleidoscope.h> #include <Kaleidoscope.h>
#include <Kaleidoscope-Leader.h> #include <Kaleidoscope-Leader.h>
static void leaderA (void) { static void leaderA() {
Serial.println ("leaderA"); Serial.println("leaderA");
} }
static void leaderTX (void) { static void leaderTX() {
Serial.println ("leaderTX"); Serial.println("leaderTX");
} }
static const KaleidoscopePlugins::Leader::dictionary_t leaderDictionary PROGMEM = LEADER_DICT static const kaleidoscope::Leader::dictionary_t leader_dictionary PROGMEM =
( LEADER_DICT({LEADER_SEQ(LEAD(0), Key_A), leaderA},
{LEADER_SEQ (LEAD (0), Key_A), leaderA}, {LEADER_SEQ(LEAD(0), Key_T, Key_X), leaderTX});
{LEADER_SEQ (LEAD (0), Key_T, Key_X), leaderTX}
); void setup() {
Serial.begin(9600);
void setup () {
Serial.begin (9600); USE_PLUGINS(&Leader);
Leader.configure (leaderDictionary); Kaleidoscope.setup();
Kaleidoscope.setup (KEYMAP_SIZE); Leader.dictionary = leader_dictionary;
Kaleidoscope.use (&Leader, NULL);
} }
``` ```
@ -75,20 +74,24 @@ changes key behaviour! Failing to do so may result in unpredictable behaviour.
The plugin provides the `Leader` object, with the following methods: The plugin provides the `Leader` object, with the following methods:
### `.configure(dictionary)` ### `.dictionary`
> Tells `Leader` to use the specified dictionary. The dictionary is an array of > Tells `Leader` to use the specified dictionary. The dictionary is an array of
> `Kaleidoscope::Leader::dictionary_t` elements. Each element is made up of two > `kaleidoscope::Leader::dictionary_t` elements. Each element is made up of two
> elements, the first being a list of keys, the second an action to perform when > elements, the first being a list of keys, the second an action to perform when
> the sequence is found. > the sequence is found.
> Not strictly a method, it is a variable one can assign a new value to.
>
> The dictionary *MUST* reside in `PROGMEM`.
### `.reset()` ### `.reset()`
> Finishes the leader sequence processing. This is best called from actions that > Finishes the leader sequence processing. This is best called from actions that
> are final actions, where one does not wish to continue the leader sequence > are final actions, where one does not wish to continue the leader sequence
> further in the hopes of finding a longer match. > further in the hopes of finding a longer match.
### `.timeOut` ### `.time_out`
> The number of milliseconds to wait before a sequence times out. Once the > The number of milliseconds to wait before a sequence times out. Once the
> sequence timed out, if there is a partial match with an action, that will be > sequence timed out, if there is a partial match with an action, that will be

@ -21,46 +21,41 @@
const Key keymaps[][ROWS][COLS] PROGMEM = { const Key keymaps[][ROWS][COLS] PROGMEM = {
[0] = KEYMAP_STACKED [0] = KEYMAP_STACKED
( (Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey,
Key_NoKey, Key_1, Key_2, Key_3, Key_4, Key_5, Key_NoKey, Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab,
Key_Backtick, Key_Q, Key_W, Key_E, Key_R, Key_T, Key_Tab, Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G,
Key_PageUp, Key_A, Key_S, Key_D, Key_F, Key_G, Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape,
Key_PageDown, Key_Z, Key_X, Key_C, Key_V, Key_B, Key_Escape,
Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift, Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift,
LEAD(0), LEAD(0),
Key_skip, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip, Key_skip, Key_6, Key_7, Key_8, Key_9, Key_0, Key_skip,
Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals, Key_Enter, Key_Y, Key_U, Key_I, Key_O, Key_P, Key_Equals,
Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote, Key_H, Key_J, Key_K, Key_L, Key_Semicolon, Key_Quote,
Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus, Key_skip, Key_N, Key_M, Key_Comma, Key_Period, Key_Slash, Key_Minus,
Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl, Key_RightShift, Key_RightAlt, Key_Spacebar, Key_RightControl,
LEAD(0) LEAD(0)),
),
}; };
static void leaderTestA(uint8_t seqIndex) { static void leaderTestA(uint8_t seq_index) {
Serial.println(F("leaderTestA")); Serial.println(F("leaderTestA"));
} }
static void leaderTestAA(uint8_t seqIndex) { static void leaderTestAA(uint8_t seq_index) {
Serial.println(F("leaderTestAA")); Serial.println(F("leaderTestAA"));
} }
static const KaleidoscopePlugins::Leader::dictionary_t leaderDictionary[] PROGMEM = LEADER_DICT static const kaleidoscope::Leader::dictionary_t leader_dictionary[] PROGMEM =
( LEADER_DICT({LEADER_SEQ(LEAD(0), Key_A), leaderTestA},
{LEADER_SEQ(LEAD(0), Key_A), leaderTestA}, {LEADER_SEQ(LEAD(0), Key_A, Key_A), leaderTestAA});
{LEADER_SEQ(LEAD(0), Key_A, Key_A), leaderTestAA}
);
void setup() { void setup() {
Serial.begin(9600); USE_PLUGINS(&Leader);
Leader.configure(leaderDictionary); Kaleidoscope.setup();
Kaleidoscope.setup(KEYMAP_SIZE); Leader.dictionary = leader_dictionary;
Kaleidoscope.use(&Leader, NULL);
} }
void loop() { void loop() {

@ -18,14 +18,15 @@
#include <Kaleidoscope-Leader.h> #include <Kaleidoscope-Leader.h>
using namespace KaleidoscopePlugins::Ranges; namespace kaleidoscope {
namespace Ranges = KaleidoscopePlugins::Ranges;
namespace KaleidoscopePlugins {
// --- state --- // --- state ---
Key Leader::sequence[LEADER_MAX_SEQUENCE_LENGTH + 1]; Key Leader::sequence_[LEADER_MAX_SEQUENCE_LENGTH + 1];
uint8_t Leader::sequencePos; uint8_t Leader::sequence_pos_;
uint32_t Leader::endTime; uint32_t Leader::end_time_;
uint16_t Leader::timeOut = 1000; uint16_t Leader::time_out = 1000;
const Leader::dictionary_t *Leader::dictionary; const Leader::dictionary_t *Leader::dictionary;
// --- helpers --- // --- helpers ---
@ -33,25 +34,24 @@ const Leader::dictionary_t *Leader::dictionary;
#define PARTIAL_MATCH -1 #define PARTIAL_MATCH -1
#define NO_MATCH -2 #define NO_MATCH -2
#define isLeader(k) (k.raw >= LEAD_FIRST && k.raw <= LEAD_LAST) #define isLeader(k) (k.raw >= Ranges::LEAD_FIRST && k.raw <= Ranges::LEAD_LAST)
#define isActive() (sequence[0].raw != Key_NoKey.raw) #define isActive() (sequence_[0].raw != Key_NoKey.raw)
// --- actions --- // --- actions ---
int8_t int8_t Leader::lookup(void) {
Leader::lookup(void) {
bool match; bool match;
for (uint8_t seqIndex = 0; ; seqIndex++) { for (uint8_t seq_index = 0; ; seq_index++) {
match = true; match = true;
if (pgm_read_word(&(dictionary[seqIndex].sequence[0].raw)) == Key_NoKey.raw) if (pgm_read_word(&(dictionary[seq_index].sequence[0].raw)) == Key_NoKey.raw)
break; break;
Key seqKey; Key seq_key;
for (uint8_t i = 0; i <= sequencePos; i++) { for (uint8_t i = 0; i <= sequence_pos_; i++) {
seqKey.raw = pgm_read_word(&(dictionary[seqIndex].sequence[i].raw)); seq_key.raw = pgm_read_word(&(dictionary[seq_index].sequence[i].raw));
if (sequence[i].raw != seqKey.raw) { if (sequence_[i].raw != seq_key.raw) {
match = false; match = false;
break; break;
} }
@ -60,9 +60,9 @@ Leader::lookup(void) {
if (!match) if (!match)
continue; continue;
seqKey.raw = pgm_read_word(&(dictionary[seqIndex].sequence[sequencePos + 1].raw)); seq_key.raw = pgm_read_word(&(dictionary[seq_index].sequence[sequence_pos_ + 1].raw));
if (seqKey.raw == Key_NoKey.raw) { if (seq_key.raw == Key_NoKey.raw) {
return seqIndex; return seq_index;
} else { } else {
return PARTIAL_MATCH; return PARTIAL_MATCH;
} }
@ -76,51 +76,42 @@ Leader::lookup(void) {
Leader::Leader(void) { Leader::Leader(void) {
} }
void void Leader::begin(void) {
Leader::begin(void) { event_handler_hook_use(eventHandlerHook);
event_handler_hook_use(this->eventHandlerHook); loop_hook_use(loopHook);
loop_hook_use(this->loopHook);
}
void
Leader::configure(const Leader::dictionary_t dictionary_[]) {
dictionary = dictionary_;
} }
void void Leader::reset(void) {
Leader::reset(void) { sequence_pos_ = 0;
sequencePos = 0; sequence_[0].raw = Key_NoKey.raw;
sequence[0].raw = Key_NoKey.raw;
} }
void void Leader::inject(Key key, uint8_t key_state) {
Leader::inject(Key key, uint8_t keyState) { eventHandlerHook(key, UNKNOWN_KEYSWITCH_LOCATION, key_state);
eventHandlerHook(key, 255, 255, keyState);
} }
// --- hooks --- // --- hooks ---
Key Key Leader::eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state) {
Leader::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState) { if (key_state & INJECTED)
if (keyState & INJECTED) return mapped_key;
return mappedKey;
if (!key_is_pressed(keyState) && !key_was_pressed(keyState)) { if (!key_is_pressed(key_state) && !key_was_pressed(key_state)) {
if (isLeader(mappedKey)) if (isLeader(mapped_key))
return Key_NoKey; return Key_NoKey;
return mappedKey; return mapped_key;
} }
if (!isActive() && !isLeader(mappedKey)) if (!isActive() && !isLeader(mapped_key))
return mappedKey; return mapped_key;
if (!isActive()) { if (!isActive()) {
// Must be a leader key! // Must be a leader key!
if (key_toggled_off(keyState)) { if (key_toggled_off(key_state)) {
// not active, but a leader key = start the sequence on key release! // not active, but a leader key = start the sequence on key release!
endTime = millis() + timeOut; end_time_ = millis() + time_out;
sequencePos = 0; sequence_pos_ = 0;
sequence[sequencePos].raw = mappedKey.raw; sequence_[sequence_pos_].raw = mapped_key.raw;
} }
// If the sequence was not active yet, ignore the key. // If the sequence was not active yet, ignore the key.
@ -128,50 +119,50 @@ Leader::eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState) {
} }
// active // active
int8_t actionIndex = lookup(); int8_t action_index = lookup();
if (key_toggled_on(keyState)) { if (key_toggled_on(key_state)) {
sequencePos++; sequence_pos_++;
if (sequencePos > LEADER_MAX_SEQUENCE_LENGTH) { if (sequence_pos_ > LEADER_MAX_SEQUENCE_LENGTH) {
reset(); reset();
return mappedKey; return mapped_key;
} }
endTime = millis() + timeOut; end_time_ = millis() + time_out;
sequence[sequencePos].raw = mappedKey.raw; sequence_[sequence_pos_].raw = mapped_key.raw;
actionIndex = lookup(); action_index = lookup();
if (actionIndex >= 0) if (action_index >= 0)
return Key_NoKey; return Key_NoKey;
} else if (key_is_pressed(keyState)) { } else if (key_is_pressed(key_state)) {
// held, no need for anything here. // held, no need for anything here.
return Key_NoKey; return Key_NoKey;
} }
if (actionIndex == NO_MATCH) { if (action_index == NO_MATCH) {
reset(); reset();
return mappedKey; return mapped_key;
} }
if (actionIndex == PARTIAL_MATCH) { if (action_index == PARTIAL_MATCH) {
return Key_NoKey; return Key_NoKey;
} }
action_t leaderAction = (action_t) pgm_read_ptr(&(dictionary[actionIndex].action)); action_t leaderAction = (action_t) pgm_read_ptr(&(dictionary[action_index].action));
(*leaderAction)(actionIndex); (*leaderAction)(action_index);
return Key_NoKey; return Key_NoKey;
} }
void void Leader::loopHook(bool is_post_clear) {
Leader::loopHook(bool postClear) { if (!is_post_clear)
if (!postClear)
return; return;
if (!isActive()) if (!isActive())
return; return;
if (millis() >= endTime) if (millis() >= end_time_)
reset(); reset();
} }
};
KaleidoscopePlugins::Leader Leader; }
kaleidoscope::Leader Leader;

@ -23,40 +23,41 @@
#define LEADER_MAX_SEQUENCE_LENGTH 4 #define LEADER_MAX_SEQUENCE_LENGTH 4
#define LEAD(n) (Key){ .raw = KaleidoscopePlugins::Ranges::LEAD_FIRST + n } #define LEAD(n) (Key) { .raw = KaleidoscopePlugins::Ranges::LEAD_FIRST + n }
#define LEADER_SEQ(...) { __VA_ARGS__, Key_NoKey } #define LEADER_SEQ(...) { __VA_ARGS__, Key_NoKey }
#define LEADER_DICT(...) { __VA_ARGS__, {{Key_NoKey}, NULL} } #define LEADER_DICT(...) { __VA_ARGS__, {{Key_NoKey}, NULL} }
namespace KaleidoscopePlugins { namespace kaleidoscope {
class Leader : public KaleidoscopePlugin { class Leader : public KaleidoscopePlugin {
public: public:
typedef void (*action_t)(uint8_t seqIndex); typedef void (*action_t)(uint8_t seq_index);
typedef struct { typedef struct {
Key sequence[LEADER_MAX_SEQUENCE_LENGTH + 1]; Key sequence[LEADER_MAX_SEQUENCE_LENGTH + 1];
action_t action; action_t action;
} dictionary_t; } dictionary_t;
Leader(void); Leader(void);
static const dictionary_t *dictionary;
void begin(void) final; void begin(void) final;
static void configure(const dictionary_t dictionary[]);
static void reset(void); static void reset(void);
static uint16_t timeOut; static uint16_t time_out;
void inject(Key key, uint8_t keyState); void inject(Key key, uint8_t key_state);
private: private:
static Key sequence[LEADER_MAX_SEQUENCE_LENGTH + 1]; static Key sequence_[LEADER_MAX_SEQUENCE_LENGTH + 1];
static uint8_t sequencePos; static uint8_t sequence_pos_;
static uint32_t endTime; static uint32_t end_time_;
static const Leader::dictionary_t *dictionary;
static Key eventHandlerHook(Key mappedKey, byte row, byte col, uint8_t keyState); static Key eventHandlerHook(Key mapped_key, byte row, byte col, uint8_t key_state);
static void loopHook(bool postClear); static void loopHook(bool is_post_clear);
static int8_t lookup(void); static int8_t lookup(void);
}; };
};
extern KaleidoscopePlugins::Leader Leader; }
extern kaleidoscope::Leader Leader;

Loading…
Cancel
Save