aboutsummaryrefslogtreecommitdiffstats
path: root/src/ffi.rs
AgeCommit message (Collapse)Author
2018-11-22Add licenseTeddy Wing
2018-11-03run_key_action(): Use `Result` from `run_action()`Teddy Wing
Now that `run_action()` returns a `Result` (e4c21b11069297d289f25834cfc3c001a4604b5f), we need to use that `Result` when we call it in `run_key_action()`. Pass on the `Result` to `ffi::run_key_action()`, and print the error message from there.
2018-11-03parser: Remove `MapAction::parse()` etc. code from second parser passTeddy Wing
Revert changes from 75d52e385fa66d6e151c9baa2cf22c2223c39ff0. These are obsolete. Now that we parse actions right in the main parser (7776832ec11ee7d4e62cfd2a6ad7735f323ab5bc), get rid of all code related to the second pass parser from `Action::String`s into `Action::Map`s, as it's obsolete. All of this action parsing is now handled by the main `map_group()` parser.
2018-11-03parser: Parse `Action::Map`s at the same time as everything elseTeddy Wing
Was having a hell of a time trying to return a `Result` from `MapAction::parse()` in 75d52e385fa66d6e151c9baa2cf22c2223c39ff0. After struggling with it, I started to think if there was a different way to go about this. Previously I had tried and failed to parse map actions in the main parser. If I could get that working, then this whole `MapAction::parse()` method would be obsolete. No need to muss with `Result`s and borrowed strings at all. When I originally wrote the parser code, I thought in terms of: "How do I get the parsed result of the `map()` parser into the `action()` parser so that it can conditionally parse one way for the `map` keyword, and another for the `cmd` keyword?". In hindsight, this was incredibly idiotic, but I guess I was too close to the code and too deep in the details. Obviously the answer to parsing differently depending on `map` or `cmd` is not to get the parsed result of `map()` into `action()`. These are parser combinators. _Of course_ we can just make two map definition parsers, one for `map` and another for `cmd`. Can't believe I never thought of that last time. Who knows how much time I wasted trying and failing, then writing a sub-optimal solution. Oh well, I guess I should just be thankful that a niggling logging problem (in `MapAction::parse()`) that turned into a maddening journey to a giant brick wall in search of a `Result` return value with correct borrows finally enlightened me to the fact that I was doing the wrong thing all along. * Comment out double-parsing code related to `MapAction::parse()` because we want to parse in a single go. No more two-pass parsing. * Split the `map_kind()` parser into two separate parsers for `map` and `cmd`. Similarly, split the `map()` parser into `map_map()` and `map_cmd()` for the same reason. Our new parser tree looks like this: map(): map definition line -> map_map(): `map` definitions -> map_kind_map(): `map` -> map_cmd(): `cmd` definitions -> map_kind_cmd(): `cmd` * Up the `recursion_limit` to 256 from 128 because I was getting stack size errors randomly when I was updating the tests for this code change. * Update `action_character()` to not parse `\n` newlines. Otherwise the newline gets included as a real `Character` in the `KeyboardKeyWithModifiers` vector. * The `map_collection_fails_without_terminating_newline()` test fails as a result of the `action_character()` parser change. Previously it relied on `map` lines parsing to `Action::String`s, which fail if there's no terminating newline. Now that `map`s parse to `Action::Map`s, the newline isn't checked by the map line parser (`map_map()`). Because the newline doesn't matter for `map` definitions, the parser would return `Ok`, failing this test even though the behaviour was correct. Change the map line to a `cmd` to have the test check the behaviour it was previously testing. * Update the tests to use parsed `Action::Map` instead of `Action::String`s where appropriate. Used this program to convert the strings into the correct source code: # action_string_to_action_map.py #!/usr/bin/env python3 import sys action_string = sys.argv[1] action = '' action += 'action: Action::Map(vec![\n' for c in action_string: action += ' KeyboardKeyWithModifiers::new(\n' action += " KeyboardKey::Character(Character::new('{}')),\n".format(c) action += ' vec![],\n' action += ' ),\n' action += ']),' print(action)
2018-11-01dome_key_state_load_map_group(): Print filename where parse error occursTeddy Wing
Instead of just printing the parse error, also print the mappings file name to context about where the error comes from.
2018-11-01dome_key_state_load_map_group(): Get rid of unnecessary variableTeddy Wing
2018-11-01dome_key_state_load_map_group(): Get rid of error chain on parseTeddy Wing
Since 'combine' errors aren't included in our error chain, calling `chain_err()` only printed the message inside, not the parser error. The trouble is, we can't add 'combine''s error to 'error-chain' because it needs a lifetime: combine::Easy::Errors<char, &str, SourcePosition> and you can't use errors with lifetimes in 'error-chain'. Since we can't use 'error-chain', just use the 'combine' error directly. This doesn't allow us to chain an addiitional error message, but does correctly print the parse error message.
2018-10-30dome_key_state_load_map_group(): Remove `expect`sTeddy Wing
Don't on errors from reading or parsing the mappings file. Instead print the error and parse an empty mappings string. Took a lot of doing to get this working because of this error: error[E0597]: `dkmap` does not live long enough --> src/ffi.rs:72:44 | 72 | match MapGroup::parse(&dkmap) | ^^^^^ borrowed value does not live long enough ... 82 | }, | - borrowed value only lives until here | = note: borrowed value must be valid for the static lifetime... Finally got tired to trying things and just decided to store the unparsed mappings string in `State` to get it to live long enough.
2018-10-30dome_key_state_load_map_group(): Fix incorrect line wrappingTeddy Wing
Otherwise the literal spaces are included in the string.
2018-10-30If no 'mappings.dkmap' file is found, use default mappingsTeddy Wing
If a mappings file is found but is empty, no mappings will be set. Hmm, that sounds wrong. We still want to keep the defaults even if only some button triggers are mapped. Making buttons do nothing is what `<Nop>` is for, not this behaviour. Darn.
2018-10-29run_key_action(): Call a function pointer when mode changesTeddy Wing
Take a function pointer argument that will be called whenever a mode is activated or deactivated. We'll be using this on the Objective-C side to play audio when the mode changes.
2018-10-29ffi::run_key_action(): Add `PlayAudio` argumentTeddy Wing
Mirror the `map::run_key_action()` function and add an extra `PlayAudio` argument, which will control whether audio cues are played when a mode is activated or deactivated. The Objective-C code will pass in this value based on the value of a `Config` setting, which will have come from a command line argument.
2018-10-29map::run_key_action(): Add conditional argument for playing audioTeddy Wing
Play audio on mode activation and deactivation depending on the value of the new argument. Decided to make it an enum instead of a bool for better readability. Will need to get rid of the `unwrap`s.
2018-10-29Rename `run_key_action_for_mode` to `run_key_action`Teddy Wing
Now that this function no longer takes a "current mode" argument, the "mode" part of the name doesn't make sense.
2018-10-28ffi: Remove `ActionKind` enumTeddy Wing
This was for the `KeyActionResult` struct, which no longer exists.
2018-10-27dome_key_logger_init(): Log `Err` instead of `unwrap()`Teddy Wing
Instead of just unwrapping, print the error message in our error format.
2018-10-27Move non-FFI functions from `ffi.rs` to `map.rs`Teddy Wing
Keep FFI functions separate from the rest.
2018-10-27Rename `cocoa_bridge.rs` to `ffi.rs`Teddy Wing
When I first created the file, it was going to be used to call Cocoa methods using the 'cocoa' crate. It's since turned into a module that contains C functions called by Objective-C code. This new name makes more sense. We'll need to move one or two non-FFI functions outside of this module for better organisation.